【问题标题】:How to wait for 2 of Promises in Promise.all to finish and then do another task如何等待 Promise.all 中的 2 个 Promise 完成然后执行另一个任务
【发布时间】:2019-08-31 20:01:31
【问题描述】:

我目前正在开发一个程序,我需要使用 Promise.all 同时运行几个函数。但在我可以继续执行任务之前,我只需要完成 2 个承诺然后运行 ​​.then(),我将如何执行此操作?

例子:

await Promise.all([Task1(),Task2(),Task3(),Task4(),Task5()]);

当仅(例如)Task1 和 Task 4 完成时,我需要它来继续代码。

我曾尝试使用 while 循环等待 Task1 和 Task2 完成,方法是在完成时设置变量,但是那样。根本不起作用。

【问题讨论】:

  • 可以任意两个吗?
  • @T.J.Crowder 这是2个具体的promise,只是随机选择的例子。
  • 那为什么不只传递两个函数而不是全部四个呢?
  • @SamH - 同样,它可以是 any 两个(例如,完成的前两个)?或者你有两个特别的想法?
  • 任务是使用 Promise.all 同时运行所有 5 个任务(因为它们需要时间来完成,秒)有时有些任务可能比其他任务需要更长的时间,这就是为什么我仍然想当 Task1 和 Task4 完成时,继续等待其他承诺,同时继续执行另一个任务。 @T.J.克劳德

标签: javascript node.js promise async-await


【解决方案1】:

Promise.all() 不会同时运行您的任务,它只会等待所有 Promise 解决,然后再解决返回的 Promise。

您的任务将在您创建每个 Promise 后立即运行。

如果你想在特定任务之后等待,只在Promise.all中包含那些任务:

const tasks = [Task2(), Task3(), Task5()];
const result1 = await Promise.all([Task1(), Task4()]);
// Task1 and Task4 are done here
const result2 = await Promise.all(tasks);
// All remaining tasks are done here

【讨论】:

    【解决方案2】:

    一种方法是构造一个新的随机承诺数组,然后只等待那些:

    let array = [Task1(),Task2(),Task3(),Task4(),Task5()];
    
    // Select any two promises after running the randomization logic
    let promises = Promise.all[array[1], array[3]];
    
    promises
      .then(() => {
        // Do stuff here
      });
    

    【讨论】:

      【解决方案3】:

      我见过这样的技巧: Promise.all(promises.map(p => p.catch(() => undefined))); 虽然很不安全。
      原答案:here

      【讨论】:

        【解决方案4】:

        在评论中,您似乎说过您事先明确知道哪两个比其余的更紧急(在本例中,它是任务 1 和任务 4)。

        然后只需使用两次Promise.all

        const allResults = Promise.all([
            Promise.all([Task1(), Task4()])
            .then(([result1, result4]) => {
                // Those two are done, do what you like with `result1` and `result4`...
                return [result1, result4];
            }),
            Task2(),
            Task3(),
            Task5()
        ])
        .then(([[result1, result4], result2, result3, result5]) => {
            // All five are done now, let's put them in order
            return [result1, result2, result3, result4, result5];
        })
        .then(/*...*/)
        .catch(/*...*/);
        

        在那里,我通过重新映射整个 then 处理程序中的顺序来保留外链中的整体 1、2、3、4、5 顺序。


        最初,我假设您想等到任何两个完成,而不是特定的两个。没有内置的,但它很容易编写:

        function enough(promises, min) {
          if (typeof min !== "number") {
            return Promise.all(promises);
          }
          let counter = 0;
          const results = [];
          return new Promise((resolve, reject) => {
            let index = 0;
            for (const promise of promises) {
              let position = index++;
              promise.then(
                result => {
                  results[position] = result;
                  if (++counter >= min) {
                    resolve(results);
                  }
                },
                reject
              );
            }
          });
        }
        

        现场示例:

        function enough(promises, min) {
          if (typeof min !== "number") {
            return Promise.all(promises);
          }
          let counter = 0;
          const results = [];
          return new Promise((resolve, reject) => {
            let index = 0;
            for (const promise of promises) {
              let position = index++;
              promise.then(
                result => {
                  results[position] = result;
                  if (++counter >= min) {
                    resolve(results);
                  }
                },
                reject
              );
            }
          });
        }
        
        const delay = (ms, ...args) => new Promise(resolve => setTimeout(resolve, ms, ...args));
        const rnd = () => Math.random() * 1000;
        
        enough(
          [
            delay(rnd(), "a"),
            delay(rnd(), "b"),
            delay(rnd(), "c"),
            delay(rnd(), "d"),
            delay(rnd(), "e")
          ],
          2
        )
        .then(results => {
          console.log(results);
        })
        .catch(error => {
          console.error(error);
        });

        【讨论】:

          【解决方案5】:

          好的,据我了解,你想做类似的事情

          const importantOnes = [Task1(), Task2()];
          const remainingOnes = [Task3(), Task4(), Task5()];
          const priorityPromise = Promise.all(importantOnes);
          
          priorityPromise.then(doPriorityStuff);
          Promise.all([priorityPromise, ...remainingOnes]).then(processTheCompleteData);
          

          【讨论】:

            猜你喜欢
            • 2017-09-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-12-27
            相关资源
            最近更新 更多