Promise API -结合2个异步调用的结果
Promise API - combining results of 2 asynchronous call
使用promise 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}
},
...
我需要得到所指示的组合结果。如何使用Angular的承诺API来做到这一点?
正如@Matt所说,您需要使用$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
,除了它将promise的数组结果扩展到其onFulfilled
函数的参数上。为了使用AngularJS中的promise方法,我们只需要去掉.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
};
这样做的美妙之处在于,由于.then
充当过滤器,我们不必处理所有错误传播的细节和存储部分结果。如果不使用错误处理程序,它会自动传播任何错误。这意味着如果任何一个输入承诺被拒绝,结果将被拒绝。如果两个承诺都成功实现,res就是这些分辨率值的数组。
我想给@ForbesLindesay的答案添加一些东西。
在我们的例子中,我们想要部分结果:如果请求失败(例如;服务器有一个小问题,我们请求的东西被别人删除了,等等),我们仍然希望收集有效的响应,并报告错误。
我发现我们需要处理每个承诺的成功和失败,返回一个将被$q.all
收集的值。
下面是我们的代码,简化并使其泛型('item'…):
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(_。地图,_。平,_。reject, _.isUndefined),但我认为用法非常清楚(这就是这个库的优点!)。
您可以使用angular-q-spread库,然后使用与@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};
});
};
- 如何在chrome扩展中存储数据/结果,以及如何使用setTimeout使其只被调用一次
- 我们如何在jQuery Datatable调用结果中启动另一个jQuery插件,而不是页面就绪函数
- 当用户移动到其他页面时,如何显示AJAX调用结果
- JSON对变量的调用结果
- 咖啡脚本化的 ajax 调用结果在实际成功时失败回调
- 使用Rally SDK 1.33创建一个包含两个findall调用结果的表
- 随机分配Dribble API调用结果
- 存储函数调用结果以供以后参考
- 从ajax调用结果更新qtip内容
- Jquery加载调用结果为空查询字符串
- 导出异步函数调用结果的变量
- 在引导模式中显示ajax调用结果
- 如何在表单提交后停止重定向到API调用结果
- 如何防止JQuery的默认动作在Ajax调用结果条件
- 在node.js中迭代大量的异步调用/结果(使用ES6 / async / bluebird / generators)
- 想要显示我调用过程的调用结果
- jQuery 管理多 Ajax 调用结果
- IE 不显示数据库中的 ajax 调用结果
- Meteor Wrapasync服务器端保存api调用结果到集合
- Node.js:在网站中显示图像作为REST API调用结果