首页 > 解决方案 > 将函数包装在 Promise 中会导致函数的代码被另一个线程并行执行吗?

问题描述

我读过很多关于 Promise 和 async/await 的文章。他们似乎都在处理返回承诺的 API 以及如何使用这些承诺。我还是有点困惑。

假设我有一个包含三 (3) 个循环的函数。假设,每个循环执行一些需要五 (5) 秒才能完成的工作,将每次迭代的结果推送到该循环的数组中。这项工作同步进行(循环 1 运行,然后是循环 2,然后是循环 3)。

然后,该函数在返回之前对所有三个循环的结果执行一些操作。总假设执行时间约为十六 (16) 秒。

如果将循环放入它们自己的函数中,包装在 promise 中,然后在async functionusing中等待await Promise.all(在对结果进行操作之前),它们是否会并行执行(因为它们在事件循环中,而不是在调用堆栈中)和一旦所有三 (3) 个承诺都解决了,该功能会继续吗?这比整个过程同步更快吗?

我想我对何时/为什么要从同步 JS 创建自己的 Promise 感到困惑?

function loop1() {
  return new Promise((resolve, reject) => {
    let loop1Counter = 0
    const loop1Array = []
    while (loop1Counter < 10 **8) {
      // Do some work
      loop1Array.push(resultOfWork)
    }
    loop1Counter += 1
    resolve(loop1Array)
  }
}

async function test() {
  const promisesToAwait = [loop1(), loop2(), loop3()]
  const results = await Promise.all(promisesToAwait)
  // Do some work with results
  return something
}

标签: javascript

解决方案


JavaScript 执行是单线程的。这意味着如果不使用 WebWorker 之类的机制,任何 javascript 代码都不会并行执行。话虽如此,使用异步代码(例如承诺)执行同步 javascript 有几个原因。

  1. 您的代码需要一段时间才能执行。

Javascript 执行与浏览器中的 UI 共享相同的线程。这意味着如果您的代码需要 5 秒来执行,则用户浏览器将在此期间被阻止。您可以改为将执行分解为多个异步执行的块,这将允许 UI 保持响应。

  1. 您正在从现有异步函数参与承诺链。

有时需要混合异步和同步代码。Promise 允许您将异步和同步代码组合到执行链中,而不必具有硬编码的依赖关系。

  1. 您遇到了堆栈大小限制。

根据您的代码和库的编写方式,有时您可能已经跑掉了堆栈,这可能导致堆栈大小异常或内存使用过多。通过异步执行一段代码,它获得了自己的新堆栈。

  1. 您正在执行库/框架中的代码,该库/框架期望您的代码异步执行。

您可以将同步代码转换为异步代码,但反之则不行。因此,一些执行您编写的代码(作为委托)的库可能要求您的代码是异步的以支持异步用例。一些库试图对此智能并根据您的返回类型进行调整,但并非所有库都如此智能。


推荐阅读