Promise.all使用场景
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Promise.all使用场景相关的知识,希望对你有一定的参考价值。
参考技术A 问题描述:Promise.all详情资料可查看: https://developer.mozilla.org/zh-CN/docs/Web/javascript/Reference/Global_Objects/Promise/all
如果参数中 promise 有一个(p2)失败(rejected),此实例回调失败(reject),就不再执行then方法回调,被catch掉了,打印了reject结果。
当然,也可以不使用Promise.all,但如果多个接口之间需要同步进行,后一个接口依赖前一个接口的返回值,这种情况做同步处理就麻烦一点了。
但是,使用Promise.all,如果有一个回调执行失败,即使其他几个promise已经进入resolved状态,then也不会执行的,或者可以说所有的promise都失败了(都不能正常取到响应结果)
下面是我的解决办法:
你如何避免使用 Promise.all 的 Promise 构造函数反模式
【中文标题】你如何避免使用 Promise.all 的 Promise 构造函数反模式【英文标题】:How do you avoid the promise constructor antipattern with Promise.all 【发布时间】:2015-11-19 18:24:10 【问题描述】:在使用多个 Promise 和 Promise.all
时如何避免 Promise 构造函数反模式?
假设我有以下代码:
getFoo = function()
return new Promise(function(resolve, reject)
var promises = [];
promises.push(new Promise(function(resolve, reject) =>
getBar1().then(function(bar1)
processBar1(bar1);
resolve(bar1);
);
));
promises.push(new Promise(function(resolve, reject) =>
getBar2().then(function(bar2)
processBar2(bar2);
resolve(bar2);
);
));
Promise.all(promises).spread(function(bar1, bar2)
var result = processBothBars(bar1, bar2);
resolve(result);
);
);
它提出了反模式的一些基本问题,错误被吞噬,以及厄运金字塔。
顺便说一句,我正在使用蓝鸟。
【问题讨论】:
而不是顶部的return new Promise(..
,return Promise.all(...
?
@KevinB 但内部承诺仍会吞下错误
为什么需要内在的承诺?为什么不能将 getBar1() 的返回值推送到数组?我对 bluebird 不太熟悉,但是,如果它遵循原生 Promise 功能,那么上面的 sn-p 中根本不需要 new Promise
。
【参考方案1】:
Fwiw bluebird 在这方面证明了一些糖:
getFoo = function()
return Promise.join(getBar1().tap(processBar1),
getBar2().tap(processBar2),
processBothBars);
【讨论】:
数组在那里做什么? @Bergi 从我没有注意到需要 processBothBars 的时候就偷偷溜进来了,所以它是.all
【参考方案2】:
无需在此处创建您自己的任何 Promise,因为 getBar1()
和 getBar2()
都已经返回 Promise - 至少我们假设是这样,因为两者都是 thenable。
提供processBar1
和processBar2
分别返回你感兴趣的结果,代码会简化如下:
var getFoo = function()
// write promises as an array literal
var promises = [
getBar1().then(processBar1),//result returned by getBar1() is automatically passed to processBar1
getBar2().then(processBar2) // ... ditto ...
];
return Promise.all(promises).spread(processBothBars);
;
【讨论】:
我不明白apply
的作用。为什么不简化为.spread(processBothBars)
?
@Bergi,我希望我能想到你的 .spread(processBothBars)
事情。我承认我的思想不是特别分散。【参考方案3】:
你可以一起摆脱new Promise
。
getFoo = function()
var promises = [];
promises.push(getBar1().then(function(bar1)
processBar1(bar1);
return bar1;
));
promises.push(getBar2().then(function(bar2)
processBar2(bar2);
return bar2;
));
return Promise.all(promises).spread(function(bar1, bar2)
var result = processBothBars(bar1, bar2);
return result;
);
// start mock
function getBar1()
return Promise.resolve(name:'bar1',processed: false);
function getBar2()
return Promise.resolve(name:'bar2',processed: false);
function processBar1(bar1)
bar1.processed = true;
function processBar2(bar2)
bar2.processed = true;
function processBothBars (bar1, bar2)
return [bar1, bar2].filter(function (bar)
return bar.processed;
).map(function (bar)
return bar.name;
);
Promise.prototype.spread = function (fn)
return this.then(function (arr)
return fn.apply(this, arr);
);
;
// end mock
var getFoo = function (fail)
var promises = [];
promises.push(getBar1().then(function (bar1)
processBar1(bar1);
if (fail)
throw 'getBar1 Failed!';
return bar1;
));
promises.push(getBar2().then(function (bar2)
processBar2(bar2);
return bar2;
));
return Promise.all(promises).spread(function (bar1, bar2)
var result = processBothBars(bar1, bar2);
return result;
);
getFoo().then(function (result)
console.log(result); // ['bar1', 'bar2']
);
getFoo(true).then(function (result)
console.log(result); // doesn't happen
).catch(function (e)
console.error(e); // Error: getBar1 Failed!
);
.then
返回一个 Promise,因此无需创建一个新的包装它的 Promise,除非您想防止错误到达外部 Promise。
【讨论】:
您忘记了 2 个then
s 中的 return
ing 值
如果您不返回任何内容,您将返回undefined
。
来自getBar1()
的错误是否会传播到getFoo()
的结果?
@Petah:是的 - 与问题中提供的代码相比
@Petah 添加了演示,带有(弱)模拟的 .spread,仅适用于具有原生 Promise 支持的浏览器。包括错误示例。以上是关于Promise.all使用场景的主要内容,如果未能解决你的问题,请参考以下文章
怎样同时获取10000+接口的返回值:Promise.all高并发限制解决方案