Javascript 使用Promise.all()实现承诺时执行操作
我可以使用Javascript 使用Promise.all()实现承诺时执行操作,javascript,asynchronous,promise,ecmascript-6,Javascript,Asynchronous,Promise,Ecmascript 6,我可以使用Promise.all(array)异步解析一组承诺。但是,.then()只有在所有这些承诺都得到解决后才会运行。我如何在承诺得到解决时采取行动 例如,我想使用Promise.all(),异步加载文章中的所有段落,这样网络请求一次全部触发。如果第1段加载完毕,我希望它呈现到页面上——但只有在第2段之前加载完毕,我才希望加载第2段。如果第3段加载完成而第2段未加载,我希望3在呈现到页面之前等待2。等等 我试过这样的方法,但我不知道下一步该怎么办: var getStuff = funct
Promise.all(array)
异步解析一组承诺。但是,.then()
只有在所有这些承诺都得到解决后才会运行。我如何在承诺得到解决时采取行动
例如,我想使用Promise.all()
,异步加载文章中的所有段落,这样网络请求一次全部触发。如果第1段加载完毕,我希望它呈现到页面上——但只有在第2段之前加载完毕,我才希望加载第2段。如果第3段加载完成而第2段未加载,我希望3在呈现到页面之前等待2。等等
我试过这样的方法,但我不知道下一步该怎么办:
var getStuff = function(number, time){
return new Promise(function(resolve, reject){
window.setTimeout(function(){resolve(`${number} - Done.`)}, time);
});
};
Promise.all([ getStuff(1, 200),
getStuff(2, 100),
getStuff(3, 250),
getStuff(4, 200),
getStuff(5, 300),
getStuff(6, 250),
getStuff(7, 5000)])
.then(function(data){
console.log(data);
});
在发出下一个请求之前,如果不使用
then()
解析每个承诺,如何获得一个又一个数据的控制台日志?有更好的方法吗?使用Promise.all
无法实现此顺序,因为Promise从Promise返回。all
等待所提供数组中的所有Promise并发解析(而不是顺序解析),然后再自行解析
相反,您可以单独创建承诺并同时激发他们的请求:
// create promises and make concurrent requests
const s1 = getStuff(1, 200);
const s2 = getStuff(2, 100);
const s3 = getStuff(3, 250);
// ...
然后创建一个关于如何处理它们的反应链(stuff1在stuff2之前,stuff2在stuff3之前,等等)
要按照创建承诺的相同顺序对承诺结果作出反应,您可以更改
getStuff
函数以使用以下命令动态链接反应:
var时间=[2001002502003002505000];
var getStuff=function(time,index){//交换参数的顺序,以便number是从Array.map传入的索引
返回新承诺((解决、拒绝)=>{
window.setTimeout(()=>{
解析(`${index+1}-Done.`);//使用index+1,因为索引从0开始
},时间);
});
};
时代
//将每次映射到一个承诺(并将数字映射到该时间的索引+1)并触发一个请求
.map(getStuff)
//动态构建承诺结果的反应链
.减少((链条、承诺)=>{
返回链
.然后(()=>承诺)
.然后(console.log);
},Promise.resolve())
.然后(()=>{
//所有承诺均已解决(所有数据均按顺序记录)
});代码>我知道它不是本地的,但是对于蓝鸟,你可以使用Promise.some
(在count
承诺兑现后填充)或Promise.mapSeries
(在系列中填充承诺)以某种方式实现你期望的流量
nem035的答案非常准确。我想指出的是,通常在这种情况下,当请求发生时,您希望执行相同的操作,当请求全部完成时,您希望执行另一个操作
您可以将.all
用于.map
:
Promise.all([ getStuff(1, 200),
getStuff(2, 100),
getStuff(3, 250),
getStuff(4, 200),
getStuff(5, 300),
getStuff(6, 250),
getStuff(7, 5000)]
.map(request => request.then(v => {
console.log("Request done! Got," v); // or some action per request
return v;
})).then(data => console.log(data));
您可以使用.map
进一步实现这一点,方法是对每个请求使用相同的函数:
Promise.all([[1, 200],
[2, 100],
[3, 250],
[4, 200],
[5, 300],
[6, 250],
[7, 5000]])
.map((a, b) => getStuff(a, b))
.map(request => request.then(v => {
console.log("Request done! Got," v); // or some action per request
return v;
})).then(data => console.log(data));
并进一步:
Promise.all([200, 100, 250, 200, 300, 250, 5000])
.map((a, i) => getStuff(a, i + 1))
.map(request => request.then(v => {
console.log("Request done! Got," v); // or some action per request
return v;
})).then(data => console.log(data));
或与蓝鸟:
const sideEffect = v => console.log("Got partial result", v));
const data = [200, 100, 250, 200, 300, 250, 5000];
Promise.map(data, (a, i) => getStuff(a, i + 1).tap(sideEffect))
.then(data => console.log(data));
当然-您应该修复后端,要求客户端对数据的不同部分发出7个请求是完全不合理的-让后端获取范围。正常操作:您可以安全地使用Promise.all()
。promise Executer将并行启动,结果将按照您将承诺插入promises数组的顺序返回。那就由你来按你喜欢的方式分类了。例如在下面的代码片段中,我们有五个承诺,每个承诺都将在5秒内随机解决。无论他们的解决时间,当最新的解决时,您将得到结果
var promises=[新承诺(v=>setTimeout(=>v(“第1段文本”),~(Math.random()*5000)),
新承诺(v=>setTimeout(=>v(“第二段文本”),~(Math.random()*5000)),
新承诺(v=>setTimeout(=>v(“第三段文本”),~(Math.random()*5000)),
新承诺(v=>setTimeout(=>v(“第四段文本”),~(Math.random()*5000)),
新承诺(v=>setTimeout(=>v(“第五段文本”),~(Math.random()*5000)),
];
所有(承诺)
。然后(result=>console.log(result.reduce((p,c)=>p+“\n”+c))代码>一些promise库有进度回调。使用本机es6无法获得这种行为?如果不向我的项目中添加另一个库,为什么不为每个承诺添加getStuff(…)
和然后render呢?我认为它不是本地可用的。你仍然可以有一系列的承诺,并且每个承诺上都有一个单独的then()
。@nem035哦,我错过了那部分。啊,这很有意义!基本上,只要我调用getStuff,他们就会发出网络请求,如果在之后执行then链,我就会得到我想要的行为,因为每个承诺都会在之前得到解决。then在链中被调用?一旦你创建了一个承诺,它就会运行你的请求。你可以在这之后的任何时候构建链,不管承诺是否在那一点得到了解决。如果承诺在你做链条之前就解决了,那么在你做链条之前,它只会保持它的价值。如果您先制作链,链将等待承诺获得价值。这就是承诺之美。它们总是异步解析,并且在使用它们编码时,您可以始终假装已经拥有了这些值。
const sideEffect = v => console.log("Got partial result", v));
const data = [200, 100, 250, 200, 300, 250, 5000];
Promise.map(data, (a, i) => getStuff(a, i + 1).tap(sideEffect))
.then(data => console.log(data));