无极API - 将2异步调用的结果(Promise API - combining results

2019-09-01 13:07发布

与诺API,如何发送两个并行的异步请求,并解决组合的结果作为响应。

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

现在,当我调用get()之类

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

我需要的综合结果所示。 如何与角承诺API做到这一点?

Answer 1:

正如@马特说,你需要使用$q.all ,但用法是不完全正确。 AngularJS不支持.done.fail ,他们不会以很喜欢那个工作,反正有作为多个值的承诺没有这样的事情,而不是你只是有一个数组的承诺。

如果你正在写这个使用全Q可以这样写:

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

在这种情况下, .spread作用类似.then ,除了它传播的阵列的结果超过其的参数的许出onFulfilled功能。 要改变这种使用来自AngularJS承诺方法,我们只需要凑合没有.spread 。 这导致了以下解决方案:

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

这样做的好处是,我们从处理错误传播的所有基本事实grity和存储部分的结果,因为释放.then作为一个过滤器。 如果你离开了错误处理程序,它会自动传播任何错误。 这意味着,如果任一输入承诺被拒绝,结果将被拒绝。 如果这两个承诺都成功完成,资源是那些分辨率值的数组。



Answer 2:

我有话要添加到@ForbesLindesay答案。

在我们的例子中,我们希望部分结果:如果请求失败,我们还是要收集的有效回应,并报告错误(如服务器有一个打嗝,我们要求的东西被别人删除等)。

我发现,我们需要处理的每一个承诺,成功与失败,返回将被收集的值$q.all

下面是我们的代码,简化和通用(“项目” ...):

var promiseList = _.map(itemList, function(item)
{
    return DataService.getISubtems(item.id)
        .then(
            function(response)
            {
                var subItems = response.data;
                $log.info('Received sub-item list;' + subItems.length + ';items received');
                return subItems;
            },
            function(reason)
            {
                $log.warn('Sub-item list not received for item;' + item.name + ';' + item.id);
                $scope.errorList.push('Sub-item list not received for item "' + item.name + '"');
            }
        );
});
$q.all(promiseList)
    .then(function(itemArray)
    {
        // We get an array of arrays interleaved with undefined value when an error was raised.
        // That's because error handling doesn't return anything, ie. returns undefined.
        // We remove these undefined values then put all operations at the same level.
        var allOperations = _(operationArray).reject(_.isUndefined).flatten().value();
        if ($scope.errorList.length > 0)
        {
            NotificationService.warning('Items Fetching', 'Errors while getting item list:\n' +
                $scope.errorList.join('\n'));
        }
        $scope._onItemListReceived(allItems);
    });

注意,我们使用Lodash(_.map,_.flatten,_.reject,_.isUndefined),但我认为使用是很清楚(这是该库的好看点!)。



Answer 3:

您可以使用角度-Q-传播库,然后使用相同的代码为@ ForbesLindesay的第一个例子:

// The module needs $q-spread as a dependency:
// angular.module('…', ['$q-spread']);

var get = function (id) {
    return $q.all([Db.get(id, "abc"), Db.get(id, "def")])
        .spread(function (res1, res2) {
            return {res1: res1, res2: res2};
        });
};


文章来源: Promise API - combining results of 2 asynchronous call