Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
173 views
in Technique[技术] by (71.8m points)

javascript - Promise API - combining results of 2 asynchronous call

With promise API, how to send two asynchronous request in parallel, and resolve the combined result as the response.

var get = function(id){
            var res1, res2;
            var deferred = $q.defer();
            Db.get(id, "abc")
                .then(function (d) {
                    //deferred.resolve(d));
                    res1 = d;
                }, function (e) {
                    //error
                });

            Db.get(id, "def")
                .then(function (d) {
                    //deferred.resolve(d));
                    res2 = d;
                }, function (e) {
                    //error
                });

            //?????? how to return {res1:res1 , res2: res2}

            return deferred.promise;
        };

now, when I call get() like

get(123).then(function(d)){
// d= {res1: res1, res2: res2}
},
...

I need to get the combined result as indicated. How to do this with Angular promise API?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As @Matt said, you need to use $q.all, but the usage isn't quite right. AngularJS doesn't support .done and .fail and they don't work quite like that anyway in that there's no such thing as a promise for multiple values, instead you just have a promise for an array.

If you were writing this using the full Q we would write:

var get = function (id) {
    return Q.all([Db.get(id, "abc"), Db.get(id, "def")])
        .spread(function (res1, res2) {
            return {res1: res1, res2: res2};
        });//the error case is handled automatically
};

In this case, .spread acts like .then except that it spreads the results of an array for a promise out over the arguments of its onFulfilled function. To change this to use the promise methods from AngularJS we just need to make do without .spread. This leads to the following solution:

var get = function (id) {
    return $q.all([Db.get(id, "abc"), Db.get(id, "def")])
        .then(function (res) {
            return {res1: res[0], res2: res[1]};
        });//the error case is handled automatically
};

The beauty of this is that we are freed from handling all the nitty grity of error propagation and storing the partial results because .then acts as a filter. If you leave out the error handler, it automatically propagates any errors. This means that if either of the input promises are rejected, the result will be rejected. If both promises are fulfilled successfully, res is the array of those resolution values.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...