与诺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做到这一点?
正如@马特说,你需要使用$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
作为一个过滤器。 如果你离开了错误处理程序,它会自动传播任何错误。 这意味着,如果任一输入承诺被拒绝,结果将被拒绝。 如果这两个承诺都成功完成,资源是那些分辨率值的数组。
我有话要添加到@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),但我认为使用是很清楚(这是该库的好看点!)。
您可以使用角度-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};
});
};