javascript - 将函数包装在 Promise 中会导致函数的代码被另一个线程并行执行吗?
问题描述
我读过很多关于 Promise 和 async/await 的文章。他们似乎都在处理返回承诺的 API 以及如何使用这些承诺。我还是有点困惑。
假设我有一个包含三 (3) 个循环的函数。假设,每个循环执行一些需要五 (5) 秒才能完成的工作,将每次迭代的结果推送到该循环的数组中。这项工作同步进行(循环 1 运行,然后是循环 2,然后是循环 3)。
然后,该函数在返回之前对所有三个循环的结果执行一些操作。总假设执行时间约为十六 (16) 秒。
如果将循环放入它们自己的函数中,包装在 promise 中,然后在async function
using中等待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 执行是单线程的。这意味着如果不使用 WebWorker 之类的机制,任何 javascript 代码都不会并行执行。话虽如此,使用异步代码(例如承诺)执行同步 javascript 有几个原因。
- 您的代码需要一段时间才能执行。
Javascript 执行与浏览器中的 UI 共享相同的线程。这意味着如果您的代码需要 5 秒来执行,则用户浏览器将在此期间被阻止。您可以改为将执行分解为多个异步执行的块,这将允许 UI 保持响应。
- 您正在从现有异步函数参与承诺链。
有时需要混合异步和同步代码。Promise 允许您将异步和同步代码组合到执行链中,而不必具有硬编码的依赖关系。
- 您遇到了堆栈大小限制。
根据您的代码和库的编写方式,有时您可能已经跑掉了堆栈,这可能导致堆栈大小异常或内存使用过多。通过异步执行一段代码,它获得了自己的新堆栈。
- 您正在执行库/框架中的代码,该库/框架期望您的代码异步执行。
您可以将同步代码转换为异步代码,但反之则不行。因此,一些执行您编写的代码(作为委托)的库可能要求您的代码是异步的以支持异步用例。一些库试图对此智能并根据您的返回类型进行调整,但并非所有库都如此智能。
推荐阅读
- java - 带有子类的 Java 条件编译
- javascript - 我有一个链接按钮,在文本字段中按回车键后需要将其聚焦
- networking - 我可以远程使用 RaspberryPi 或其他设备进行所有输入吗
- arcgis - 修改由 ArcGIS Web AppBuilder 创建的代码
- javascript - Javascript:网页中与脚本相关的 HTML 标签的不正确中和(基本 XSS)
- jquery - 使用 jquery animate 方法在容器 div 周围移动框 div
- postgresql - Postgres 将列出我的数据库,但当我尝试连接它时它不存在
- html - 为 a 设置垂直对齐
- swift - 如何在 Swift 中使用调用者的类型推断静态泛型方法中的类型
- javascript - Dialogflow - Hangouts Chat 负载示例