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

时间:2017-10-13 08:28:22

标签: javascript promise

在下面的示例中,我希望在几秒钟后解析数组的每个元素。它现在的表现如何在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");
});

6 个答案:

答案 0 :(得分:3)

使用新的Async / Await,现在已经广泛实施了。如果没有,您可以转换旧浏览器。

您可以创建更加线性且更容易理解的代码。

值得一提的是,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();

答案 1 :(得分:2)

这是正常的行为,因为Promise是异步的并且实际上是并发的。 Promise.all只是等待所有的promises完成,它不是一个在另一个之后调用promise的精化队列。如果你想一个接一个地执行操作,只是不使用promises,使用正常的同步周期:)

答案 2 :(得分:1)

它将所有值传递给map函数,然后迭代它们并为它们创建异步工作4秒。它不会在彼此之后调用setTimeout

您的4秒仅与setTimeout的回调有关,而与map功能无关,这意味着将至少在4秒后调用回叫。因此引擎为setTimeout创建了不同的线程,并在4秒后调用它。当另一个线程中的第一个时间流逝时,在JS线程中它传递第二个值并为每个项目执行相同的操作。

可以使用RxJS

完成一个解决方案

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

答案 3 :(得分:1)

每次增加您的计时器,乘以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");
    });

16秒后显示“完成”。

答案 4 :(得分:1)

创建承诺时,超时将设置为4秒,并在~4秒后同时到期。 要实现所需的行为,您可以执行以下操作:

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

答案 5 :(得分:0)

如果您需要按顺序运行每个承诺,而不是并行运行。 你可以使用异步函数,然后等待继续使用promises。 对于无异步功能解决方案,您可以使用此功能较旧的解决方案。使用数组reduce方法。请注意我正在生成一系列函数,每个函数都会返回一个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'); });