我怎样才能在 Angular 服务中调用两个承诺并返回组合数据



我有一个服务,它调用另外两个异步服务并返回一些组合数据,但是如何在 AngularJS 中做到这一点。

我有一个控制器,我想在其中调用这两个类似于这样的方法:

function ServiceC(serviceA,serviceB) {
    var dataA = serviceA.GetAsyncStuff(); //returns promise
    var dataB = serviceB.GetAsyncStuff(); //returns promise
    return 'Greetings ' + dataA + dataB;
}

有没有比实际嵌套 Then 方法调用更聪明的方法,如下所示:

    function ServiceC(serviceA,serviceB) {
        var dataA = serviceA.GetAsyncStuff().then(function(respA){
            var dataB = serviceB.GetAsyncStuff().then(function(respB){
                 return 'Greetings ' + respA.data + respB.data;
            });
    });
}

这个例子当然有点简化。

这是一个演示 plunker: http://plnkr.co/edit/yCrbwnarVDqwC4GBxhGg?p=preview

您需要使用$q.all

app.factory('myService', function($q, serviceA, serviceB, serviceC){
  // $http returns a response object so we need to extract the data
  var fn = function(res){
    return res.data;
  };
  var promises = [
    serviceA.GetAsyncStuff().then(fn),
    serviceB.GetAsyncStuff().then(fn)
  ];
  return $q.all(promises).then(function(data){
    // you can manipulate consolidated data here
    // data.push(serviceC);
    return data;
  });
});

从$q文档中:

$q#全部(承诺);

多个承诺合并为一个承诺,当解析所有输入承诺时,将解析该承诺。

返回

返回将使用值数组/

哈希解析的单个承诺,每个值对应于承诺数组/哈希中同一索引/键处的承诺。如果任何承诺通过拒绝解决,则此生成的承诺将以相同的拒绝值被拒绝。

function ServiceC(serviceA,serviceB) {
        var _totalData = {};
        var dataA = serviceA.GetAsyncStuff().then(function(respA){
            _totalData = respA;
        });
        var dataB = serviceB.GetAsyncStuff().then(function(respB){
            _totalData += respB;
            });
        return{ totalData: _totalData}
}

我说第一个更好,因为它有两个不同的调用,您可以添加数据并在最后返回它,在第二个示例中,您在服务下使用服务,这将产生节省一个服务价值的开销,直到第二个服务被调用并调用其数据, 你可以看到第二个网络压力是花费大量时间来获取资源和返回资源。

我们可以调用服务和返回承诺。

myApp.provider("myService", function($http,$q){
    var serviceOneData = {},
    serviceTwoData = {};
    //call service 1
     return {
       serviceOneData : serviceOneData ,
       serviceTwoData : serviceTwoData ,
        getService1: function(){
var deferred = $q.defer();
     $http({method: 'GET',url:'Service1',
                headers:{
                    'Access-Control-Allow-Origin': '*'}}).
                success(function(data,status,header,config){
                serviceOneData = data;
                deferred.resolve();

                })
                .error(function (data,status,header,config) {
                    deferred.reject();
                });
    //call service 2
    return deferred.promise;
        },
         getService2: function(){
var Seconddeferred = $q.defer();
     $http({method: 'GET',url:'Service2',
                headers:{
                    'Access-Control-Allow-Origin': '*'}}).
                success(function(data,status,header,config){
                    serviceTwoData = data;
                    Seconddeferred.resolve();
                })
                .error(function (data,status,header,config) {
                    Seconddeferred.reject();
                });
    //call service 2
    return Seconddeferred.promise;
         },
         getService : getService1().then(getService2()).
            then(
            return serviceOneData + serviceTwoData
          );
     }
} );

你可以链接承诺:

angular.module('app',[])
            .factory('Service1',function($q,$timeout){
                return {
                    f: function(){
                        var deferred = $q.defer();
                        $timeout(function() {
                           deferred.resolve('Service 1');
                        },1000);
                        return deferred.promise;
                    }
                }
            })
            .factory('Service2',function($q,$timeout,Service1){
                return {
                    f: function(){
                        var deferred = $q.defer();
                        Service1.f().then(function(data){
                            $timeout(function() {
                                deferred.resolve('Service 2 '+ data);
                            },1000);
                        });
                        return deferred.promise;
                    }
                }
            })
            .controller('MainCtrl', function($scope,Service2){
                var promise2 = Service2.f();
                    promise2.then(function(data2){
                        console.log(data2);
                    });
            });

或者只是使用

$q.all([Service1,Service2]).then

http://denisonluz.com/blog/index.php/2013/10/06/angularjs-returning-multiple-promises-at-once-with-q-all/

最好的办法是使用 $q.all ,这样可以确保在尝试执行函数之前已解析所有请求的承诺

function ServiceC(serviceA, serviceB, $q) {
    var dataA = serviceA.GetAsyncStuff(); //returns promise
    var dataB = serviceB.GetAsyncStuff(); //returns promise
    $q.all([dataA, dataB]).then(doSomething);
}

编辑:如果您需要返回数据,则必须返回承诺。您可以只返回$q.all,也可以在$q.all解决后解决新承诺,例如

function ServiceC(serviceA, serviceB, $q) {
    var dataA = serviceA.GetAsyncStuff(); //returns promise
    var dataB = serviceB.GetAsyncStuff(); //returns promise
    var deferred = $q.defer();
    $q.all([dataA, dataB]).then(function (promises) {
        deferred.resolve('Greetings ' + promises[0] + promises[1]);
    });
    return deferred.promise;
}

最新更新