AngularJS: Waiting for an asynchronous call

前端 未结 3 1509
清歌不尽
清歌不尽 2021-01-04 12:43

I can\'t wrap my head around AngularJS\' concept of promises.

I have a provider:

var packingProvider = angular.module(\'packingProvider\',[]);

packi         


        
相关标签:
3条回答
  • 2021-01-04 13:00

    Try

    var packingProvider = angular.module('packingProvider',[]);
    
    packingProvider.provider('packingProvider',function(){
        return{
           $get: function($http){
               return{
                  getPackings: function(){
                      return $http.post('../sys/core/fetchPacking.php').then(function(response){
                          return response.data; // packings
                      });
                  }
               }
           }
       }
    });
    

    Then

    packingProvider.getPackings().then(function(packings){
        console.log(packings);
    });
    

    Main idea: you need to return the promise object from the getPackings function. Not sure if you can make the call to it synchronous but it's almost definitely not a great idea to do so. Also, if you want to make "packings" a model object on your controller and use for a two-directional binding, you can safely assign the promise object, which Angular will resolve as soon as data comes through:

    $scope.packings = packingProvider.getPackings();
    

    UPDATE

    As of 1.2.0-rc.3 promise unwrapping has been deprecated (https://github.com/angular/angular.js/blob/master/CHANGELOG.md#120-rc3-ferocious-twitch-2013-10-14) , so the line of code above will not result in a two-directional binding any more.

    0 讨论(0)
  • 2021-01-04 13:03

    The return value from within your then method isn't returning when you think it is; it's returning later.

    In the statement var packings = packingProvider.getPackings(); the return value is undefined because the promise returned from $http is asynchronous. That means that the call to $http.post happens, does not complete, then your function returns. In JS functions that don't return anything return undefined. The post call completes later and executes return packings; which gets returned to nowhere.

    The getPackings method should probably return the promise from $http.post directly. That way any code that wants to use this method can call then on the promise directly and set the value the way it needs to. In a controller you could assign that promise directly to the $scope and use it in your view. Here's a nice post that explains that particular feature: http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/

    Incidentally, it looks like you've got a long-winded service declaration there; any reason not to shorten it to something like this?

    var module = angular.module('packing', []);
    
    module.service('packing', function($http) {
      return {
        getPackings: function() {
          return $http.post('../sys/core/fetchPacking.php');
        }
      };
    });
    

    I'm relatively new to AngularJS but I don't see any gain in all that typing. ( =

    0 讨论(0)
  • 2021-01-04 13:13

    There are a ton of resources available that show you how to use Deferreds/Promises with jQuery. Try a search for those and that may help you get over this hurdle. Afaik, the AngularJS promises are the same as the jQuery promises.

    A jQuery promise is used something like this:

    var getPackings = function() { return $.get('../sys/core/fetchPacking.php'); };
    var packings;
    $.when(getPackings()).then(function(data){ packings = data; console.log(packings) });
    

    Keep in mind though that jQuery ajax calls have functions such as .done, .success, etc.. that would replace the generic Deferreds' .when().then() functions.

    In the above jQuery method, you can see that we have to set the data and output it in the .then() function, because you cannot guarantee that the asynchronous process is done anywhere else. So ideally you would call to whatever function continues your processing in the .then() function, like so:

    $.when(myAsyncFunc()).then(myAppCanContinue(dataReturnedByAsyncFunc));
    

    Angular is going to follow the same logic. If you understand the above, it should be easier to understand how to accomplish this in Angular. Also, check out this article that gives simple examples: http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/

    In order to get your code to work, you will need to do something like this:

    packingProvider.provider('packingProvider',function(){
        return{
           $get: function($http){
               return{
                  getPackings: function(){
                      return $http.post('../sys/core/fetchPacking.php');
                  }
               }
           }
       }
    });
    var packings = packingProvider.getPackings();
    
    packings.then(function(data) { console.log(data)});
    
    0 讨论(0)
提交回复
热议问题