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