【问题标题】:Why does Promise.all not run 2 functions asynchronously? [duplicate]为什么 Promise.all 不能异步运行 2 个函数? [复制]
【发布时间】:2020-11-09 10:58:22
【问题描述】:

我有一个节点 js 程序。我想使用 Promise.all 异步运行 2 个倒计时函数。预计两个功能会一起倒计时,程序在5秒内结束。但它们按顺序运行,程序在 10 秒内结束。如何异步运行它们?感谢您的帮助。

const delayOneSecond = () => {
    let start = new Date().getTime();
    while (new Date().getTime() - start < 1000) { }
    return;
}

const OK = true;

const func = (name, num) => {
    return new Promise(
        function (resolve, reject) {
            if (OK) {
                for(let i=1; i<=num; i++){
                    delayOneSecond();
                    console.log(`[${name}] - ${num - i}`);
                }
                resolve('OK');
            } else {
                reject(new Error('Not OK'));
            }
        });
}

Promise.all([func('xxx', 5), func('ooo', 5)])
  .then((res) => { console.log(res); })

【问题讨论】:

  • 你的代码没有异步,所以它是同步运行的。 Promise 不会使代码异步,它们将异步调用的处理抽象为易于管理的形式。要使其异步运行,您需要添加本质上是异步的东西,即 ajax 调用或 setTimeout 等。

标签: javascript node.js asynchronous promise


【解决方案1】:

您的while 循环是一个让JavaScript 在一秒钟内保持忙碌的循环。在此期间,没有其他 JavaScript 代码可以执行,无论您计划执行什么其他操作。在您的情况下,这意味着第二个 func('ooo', 5) 在第一个调用返回之前不会启动。

实际上,您提供给new Promise 的回调不应该是一段阻塞代码:它应该相对快速地执行并返回。它的工作主要是调用一些(低级)API 来触发 asynchronous 事件,您的代码将监听该事件。到时候resolve就可以调用了。

您可以为此使用 Web API(或其他一些异步库的 API),它会为您提供setTimeout:该函数将允许您在延迟(例如 1 秒)过去时收到通知,但仍会执行完成其余代码(也可以调用setTimeout)。

如果您在setTimeout 调用它的回调时解决了一个promise,那么您就有了一个有用的、非阻塞的delayOneSecond 实现。然后可以很容易地与await结合:

const delayOneSecond = () => new Promise(resolve => setTimeout(resolve, 1000));

const func = async (name, num) => {
    for(let i=1; i<=num; i++){
        await delayOneSecond();
        console.log(`[${name}] - ${num - i}`);
    }
    return "OK";
}

Promise.all([func('xxx', 5), func('ooo', 5)])
  .then((res) => { console.log(res); })

虽然这里看起来func 的执行仍然需要 5 秒才能返回,但实际上并非如此。它在到达第一个await 时返回。它在那个时候返回一个承诺(所以没有任何延迟),并且可以继续执行第二次调用func

当它们的delayOneSecond() 承诺解决时,即(至少)一秒后,这两个函数执行上下文得到恢复。只有这样他们的for 循环才会继续......这种情况一个接一个地发生:他们不会并行运行他们的 JavaScript:一个函数上下文被恢复,直到下一个 await,然后同样发生另一个函数上下文。

【讨论】:

  • 对于 OP:这称为“忙等待”,以防您想通过 Google 搜索更多信息。
猜你喜欢
  • 2021-01-15
  • 2023-01-23
  • 1970-01-01
  • 2019-12-21
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-10
相关资源
最近更新 更多