简体   繁体   English

使用超时解析包含Promises数组的Promise.all

[英]Resolve Promise.all containing array of promises with timeout

In the below example I'd like to resolve each element of the array after a couple of seconds. 在下面的例子中,我想在几秒钟后解析数组的每个元素。 How it behaves now is it will solve the Promise after 4 seconds, I expect it to resolve after 16seconds because there is 4 element. 它现在的表现如何在4秒后解决Promise,我希望它在16秒后解决,因为有4个元素。

const numbers = [1, 2, 3, 4];

const promises = numbers.map(number => {
    return new Promise(resolve => {
        setTimeout(() => {
          console.log(number);
            resolve(number);
        }, 4000);
    });
});


Promise.all(promises).then( () => {
    console.log("Done");
});

Using the new Async / Await, that's now pretty much widely implemented. 使用新的Async / Await,现在已经广泛实施了。 And if not, you can transpile for old browsers. 如果没有,您可以转换旧浏览器。

You can create code, that's much more linear and easier to follow. 您可以创建更线性且更易于遵循的代码。

It's also worth mentioning, bluebird has a promise based map, that has a concurrency option that would be ideal for the map bit. 值得一提的是,bluebird有一个基于promise的映射,它具有一个并发选项,非常适合映射位。

 const numbers = [1, 2, 3, 4]; async function delay(ms) { return new Promise((resolve) => { setTimeout(resolve, ms); }); } //pretend show number async async function showNumber(l) { return new Promise((resolve) => { setTimeout(() => { console.log(numbers[l]); resolve(); }); }); } async function doNumbers() { for (let l = 0; l < numbers.length; l ++) { await delay(4000); await showNumber(l); } console.log("Done"); } doNumbers(); 

This is the normal behaviour, because the Promise are asyncronous and practically concurrent. 这是正常的行为,因为Promise是异步的并且实际上是并发的。 Promise.all simply wait for all promises to be complete, it isn't an elaboration queue which call a promise after the other. Promise.all只是等待所有的promises完成,它不是一个在另一个之后调用promise的精化队列。 If you want to execute the operations one after the other simply don't use promises, use a normal sync cycle :) 如果你想一个接一个地执行操作,只是不使用promises,使用正常的同步周期:)

It passes all values to the map function and then iterates over them and creates asynchronous work for them 4 seconds. 它将所有值传递给map函数,然后迭代它们并为它们创建异步工作4秒。 It is not going to call setTimeout after each another. 它不会在彼此之后调用setTimeout

Your 4 seconds are related only to the setTimeout 's callback, not to the map function, which means that the callback will be called at least after 4 seconds. 你的4秒只与setTimeout的回调有关,而不是与map函数有关,这意味着回调将至少在4秒后被调用。 So engine creates different thread for the setTimeout and left it to be called after 4 seconds. 因此引擎为setTimeout创建了不同的线程,并在4秒后调用它。 When the time is elapsing for the first one in another thread, in JS thread it passes the second value and do the same thing for each item. 当另一个线程中的第一个时间流逝时,在JS线程中它传递第二个值并为每个项目执行相同的操作。

One solution can be done using RxJS 可以使用RxJS完成一种解决方案

 Rx.Observable.from([1,2,3,4]).map(value => Rx.Observable.of(value).delay(4000)).concatAll().subscribe(x => console.log(x)); 
 <script src='https://unpkg.com/@reactivex/rxjs@5.4.3/dist/global/Rx.js'></script> 

Increment your timer everytime, by multiplying it by number : 每次增加计时器,乘以number

 const numbers = [1, 2, 3, 4]; const promises = numbers.map(number => { return new Promise(resolve => { setTimeout(() => { console.log(number); resolve(number); }, number*4000); }); }); Promise.all(promises).then( () => { console.log("Done"); }); 

It displays "Done" after 16 seconds. 它在16秒后显示“完成”。

When you create promises, the timeouts will be set for 4 seconds and will expire simultaneously after ~4 seconds. 创建promises时,超时将设置为4秒,并在~4秒后同时到期。 To achieve desired behaviour, you can do something like this: 要实现所需的行为,您可以执行以下操作:

const numbers = [1, 2, 3, 4];

const promises = numbers.map((number, i) => {
    return new Promise(resolve => {
        setTimeout(() => {
          console.log(number); 
            resolve(number);
        }, 4000*(i+1));
    });
});


Promise.all(promises).then( () => {
    console.log("Done");
});

If you need to run each promise in sequential, not in parallel. 如果您需要按顺序运行每个承诺,而不是并行运行。 you can use async functions and then await on promises in sequent. 你可以使用异步函数 ,然后在后续等待承诺。 for none async function solutions, you can use this functional older solution. 对于无异步功能解决方案,您可以使用此功能较旧的解决方案。 using array reduce method. 使用数组reduce方法。 pay attention I'm generating an array of functions and each function returns a promise. 注意我正在生成一个函数数组,每个函数都返回一个promise。

const numbers = [1, 2, 3, 4];

numbers.map(number => () => {
    return new Promise(resolve => {
       setTimeout(() => {
           console.log(number);
           resolve(number);
       }, 4000);
    });
}).reduce(
    (promise, asyncJob) => promise.then(() => asyncJob()),
    Promise.resolve()
).then(() => { console.log('done'); });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM