如何异步调用函数

时间:2015-08-02 17:07:54

标签: angularjs angularjs-scope angular-ui-router

我有一些要在控制器中调用的函数列表

$scope.trader = {};

$scope.getUserLocation();
$scope.searchPaymentMethod($scope.trader.cityname);
$scope.getUserCurrency();

并且每个函数都进行HTTP调用以获取一些数据。说getUserLocation这样做......

$scope.getUserLocation = function() {
    var dataPromise = locationServiceCustomised.getCurrentLocation();
    dataPromise.then(function(result) {
        $scope.trader.cityname=result.countryName;
    });
}

并且这些函数将一些值设置为$scope.trader,其值用于调用另一个函数。

现在如何逐个异步调用这些函数,使这些函数一个接一个地工作。

我的完整代码有点像这样......

$scope.trader = {};

$scope.getOfferList = function() {

    if($scope.trader.cityname == null || $scope.trader.cityname == '') {
            $scope.getUserLocation();
        }

    $scope.searchPaymentMethod($scope.trader.cityname);
    $scope.getUserCurrency();
}

$scope.getUserLocation = function() {
    var dataPromise = locationServiceCustomised.getCurrentLocation();
    dataPromise.then(function(result) {
        $scope.trader.cityname=result.countryName;
    });
}

$scope.searchPaymentMethod = function(country) {
    locationService.paymentMethod({cityname: country}, function(data) {
        ------- Some Functionality-------
    });
};

$scope.getOfferList();

2 个答案:

答案 0 :(得分:1)

你基本上需要链接承诺。所以,首先,你的所有功能必须返回一个承诺。因此,对于您的第一个功能,您将拥有:

$scope.getUserLocation = function() {
   var deferred = $q.defer();
   locationServiceCustomised.getCurrentLocation.then(function(result) {
       deferred.resolve(result);
    });
   return deferred;
}

然后把它链起来:

$scope.getUserLocation()
    .then($scope.searchPaymentMethod)        
    .then($scope.getUserCurrency);

,其中

$scope.searchPaymentMethod = function(input) {
   var deferred = $q.defer();
   $scope.trader.cityname = input.cityname;
   // do some computationn
   deferred.resolve(whateveryouwanttoreturn);
   returnn deferred;
}

答案 1 :(得分:1)

如果您具有依赖于从先前异步函数获得的值的异步函数,则需要使用.then链接promise。如果可以并行调用函数,则需要使用$q.all

在您的情况下,searchPaymentMethod严格依赖于getLocation的值,而getUserCurrency可以并行完成。

$scope.getOfferList = function() {

   var paymentMethodPromise = 
     $q.when($scope.trader.cityname)
       .then(function(cachedLocation){
          if (cachedLocation) return cachedLocation;

          return getUserLocation();
       })
       .then(function(location){
          // cache, if needed, but better do this in a service
          $scope.trader.cityname = location;
          return searchPaymentMethod(location);
       });

   var currencyPromise = getUserCurrency();

   // when all complete, calculate offerList
   return $q.all({ 
                  paymentMethod: paymentMethodPromise,
                  currency: currencyPromise })
            .then(function(data){
               var paymentMethod = data.paymentMethod,
                   currency = data.currency;

               // based on that get offerList
               return offersList;
            })

};

毋庸置疑,为了实现这一目标,期望所有这些功能(即searchPaymentMethodgetUserLocation等......)返回正确值的承诺。例如,getUserLocation现在没有这样做,应该更改为以下内容:

function getUserLocation(){
   return locationServiceCustomised
           .getCurrentLocation()
           .then(function(location){
             // manipulate the result if needed
             return location.cityName;
           })
}

其他一些注意事项:

  1. 您不需要公开$scope上的每个函数 - 只公开需要从View中调用的函数,例如<button ng-click="getOfferList()">

  2. 最好将缓存或未缓存的决定留给服务(应该实现这些功能),并为控制器留下一个干净的API。