如何在Angular服务中调用两个promise并返回组合数据

时间:2014-02-18 21:01:04

标签: angularjs promise

我正在调用另外两个异步服务并返回一些组合数据的服务,但是如何在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;
            });
    });
}

这个例子当然有点简化。

5 个答案:

答案 0 :(得分:5)

这是一个演示插件: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 docs

  

<强> $ Q#所有(许诺);

     

将多个promises组合成一个promise,当所有输入promise都被解析时解析。

     

<强>返回

     

返回将使用值的数组/散列解析的单个promise,每个值对应于promises数组/散列中相同索引/键的promise。如果任何承诺通过拒绝得到解决,则此结果承诺将被拒绝并具有相同的拒绝价值。

答案 1 :(得分:0)

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}
}

我说第一个更好,因为它有两个不同的调用,你可以添加你的数据并在最后返回它,在你的第二个例子中,你使用服务下的服务,这会产生一个开销,用于保存一个服务直到第二个服务被调用并调用它的数据,你可以看到网络压力第二个是花费很多时间来获取资源并返回资源。

答案 2 :(得分:0)

我们可以同时调用服务并返回承诺。

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
          );

     }

} );

答案 3 :(得分:0)

最好的办法是使用$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;
}

答案 4 :(得分:0)

你可以链接承诺:

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/