作为承诺开始使用Promise.all履行执行操作()

问题描述 投票:17回答:4

我可以异步解决一堆与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()每个承诺?有一个更好的方法吗?

javascript asynchronous promise ecmascript-6
4个回答
18
投票

使用Promise.all因为承诺返回从Promise.all等待从提供的阵列中的所有承诺,同时分解(而不是按顺序),它本身解决之前,是无法实现这个顺序。

相反,你可以单独创建的承诺,并同时他们的请求的火:

// create promises and make concurrent requests
const s1 = getStuff(1, 200);
const s2 = getStuff(2, 100);
const s3 = getStuff(3, 250);
// ...

然后,创建关于如何处理它们(stuff2之前stuff1,stuff3之前stuff2等)的反应链

// create a chain of reaction order to the results of parallel promises
s1
  .then(console.log) // s1 resolved: log result
  .then(() => s2)    // chain s2
  .then(console.log) // s2 resolved: log result
  .then(() => s3)    // chain s3
  // ...
  .then(() => {      // chain another function at at the end for when all promises resolved
    // all promises resolved (all data was logged)
  }

反应承诺在承诺创建顺序相同的结果,你可以改变你getStuff功能动态连锁使用Array.prototype.reduce的反应:

var times = [200, 100, 250, 200, 300, 250, 5000];

var getStuff = function(time, index) { // swap the order of arguments so number is the index passed in from Array.map
  return new Promise((resolve, reject) => {
    window.setTimeout(() => {
      resolve(`${index + 1} - Done.`); // use index + 1 because indexes start at 0
    }, time);
  });
};

times
  // map each time to a promise (and number to the index of that time + 1) and fire of a request
  .map(getStuff)
  // dynamically build a reaction chain for the results of promises
  .reduce((chain, promise) => {
    return chain
      .then(() => promise)
      .then(console.log);
  }, Promise.resolve())
  .then(() => {
    // all promises resolved (all data was logged in order)
  });

6
投票

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度的要求 - 有后台拿范围。


2
投票

我知道这不是本地人,但与蓝鸟你可以使用Promise.some(以fullfill count承诺已履行后)或Promise.mapSeries(串联fullfill承诺)以某种方式达到你所期望的流量。

Bluebird API


0
投票

正常运行:您可以放心地使用Promise.all()。该承诺executers将同时被解雇,结果将在你插入你的承诺到承诺阵列的顺序返回。然后就看你对它们进行排序,你喜欢的方式。如下面的代码片段,我们有五个承诺将每5秒钟内随机解决。不管它们的解决时间,你将得到的结果最新做出决议时;

var promises = [ new Promise( v => setTimeout(_ => v("1st paragraph text"),~~(Math.random()*5000))),
                 new Promise( v => setTimeout(_ => v("2nd paragraph text"),~~(Math.random()*5000))),
                 new Promise( v => setTimeout(_ => v("3rd paragraph text"),~~(Math.random()*5000))),
                 new Promise( v => setTimeout(_ => v("4th paragraph text"),~~(Math.random()*5000))),
                 new Promise( v => setTimeout(_ => v("5th paragraph text"),~~(Math.random()*5000))),
               ];
Promise.all(promises)
       .then(result => console.log(result.reduce((p,c) => p + "\n" + c)));

你想要什么:但你不希望只要等待的最后一个结束,而是要处理他们的顺序,他们尽快得到解决。然后Array.prototype.reduce()是你最好的朋友在这里。如

var promises = [ new Promise( v => setTimeout(_ => v("1st paragraph text"),~~(Math.random()*5000))),
                 new Promise( v => setTimeout(_ => v("2nd paragraph text"),~~(Math.random()*5000))),
                 new Promise( v => setTimeout(_ => v("3rd paragraph text"),~~(Math.random()*5000))),
                 new Promise( v => setTimeout(_ => v("4th paragraph text"),~~(Math.random()*5000))),
                 new Promise( v => setTimeout(_ => v("5th paragraph text"),~~(Math.random()*5000)))
               ];
promises.reduce((p,c) => p.then(result => (console.log(result + "\n"),c)))
        .then(result => (console.log(result + "\n")));

请运行该代码多次看到代码的行为。该文本将尽快更新的承诺做出决议,但只有当它是轮到。所以,如果一日2次后消失,我们将看到第1次和第2次出现在他们的订单一次,但他们不会等待3到等解析...

© www.soinside.com 2019 - 2024. All rights reserved.