为了账号安全,请及时绑定邮箱和手机立即绑定

Javascript async 和 await 等同于多线程吗?

Javascript async 和 await 等同于多线程吗?

肥皂起泡泡 2022-12-09 17:10:59
是在用async粗人await的线吗?许多个月前,我学会了如何在 Android 上编写多线程 Java 代码。我记得我必须创建线程、启动线程等。现在我正在学习 Javascript,我刚刚了解了async和await。例如:async function isThisLikeTwoThreads() { const a = slowFunction(); const b = fastFunction(); console.log(await a, await b);}这看起来比我以前做的要简单得多,而且直观得多。slowFunction()将首先启动,然后fastFunction()将启动,并console.log()会等到两个功能在记录之前解决 - 并且slowFunction()可能fastFunction()同时运行。我希望它最终在浏览器上是否是单独的线程。但它看起来像粗糙的多线程一样走路和说话。是吗?
查看完整描述

3 回答

?
元芳怎么了

TA贡献1798条经验 获得超7个赞

是在用async粗人await的线吗?

一点都不。它只是使用 promises 的语法糖(真的非常有用的糖),而这又只是一种(真的非常有用的)使用回调的形式化方式。它很有用,因为您可以异步等待(不阻塞 JavaScript 主线程)本质上是异步的事物(如 HTTP 请求)。

如果您需要使用线程,请使用web workersNode.js worker threads或您的环境提供的任何多线程。根据规范(现在),一次只允许一个线程在给定的 JavaScript“领域”(非常松散:您的代码运行的全局环境及其关联的对象等)中工作,因此只有一个线程一次可以访问该领域内的变量等,但线程可以通过消息传递(包括在它们之间传输对象而不制作副本)和共享内存进行协作。

例如:


async function isThisLikeTwoThreads() {

 const a = slowFunction();

 const b = fastFunction();

 console.log(await a, await b);

}

isThisLikeTwoThreads以下是调用时代码的作用:

  1. slowFunction同步调用并将其返回值分配给a.

  2. fastFunction同步调用并将其返回值分配给b.

  3. isThisLikeTwoThreads到达时await a,它包装a在一个承诺中(就像你做的那样Promise.resolve(a))并返回一个新的承诺(不是同一个)。让我们调用围绕a“ aPromise”的承诺和函数“ functionPromise”返回的承诺。

  4. 稍后aPromise结算时,如果被拒绝functionPromise,则以相同的拒绝原因拒绝,并跳过以下步骤;如果满足,则下一步完成

  5. 中的代码isThisLikeTwoThreads继续包装b在 promise ( bPromise) 中并等待其解决

  6. 结算时bPromise,如果被拒绝functionPromise则以同样的拒绝原因被拒绝;如果已实现,则中的代码isThisLikeTwoThreads会继续记录实现值aPromisebPromise然后functionPromise用该值实现undefined

上面的所有工作都是在完成调用的 JavaScript 线程上isThisLikeTwoThreads完成的,但它分布在多个“作业”(JavaScript 术语;HTML 规范称它们为“任务”,并详细说明了它们如何进行'在浏览器上处理)。如果slowFunctionfastFunction启动了一个异步进程并为此返回了一个承诺,那么当 JavaScript 线程正在做其他事情时,该异步进程(例如,浏览器执行的 HTTP 调用)可能会继续与 JavaScript 线程并行,或者(如果它也在主线程上的 JavaScript 代码)可能已经竞争 JavaScript 线程上的其他工作(通过将作业添加到作业队列和线程在循环中处理它们来竞争)。

但是使用 promises 不会添加线程。:-)


查看完整回答
反对 回复 2022-12-09
?
杨魅力

TA贡献1811条经验 获得超6个赞

我建议您阅读本文以了解答案是否定的:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop


总而言之,运行时使用多个线程进行内部操作(网络、磁盘...用于 Node.js 环境、渲染、indexedDB、网络...用于浏览器环境)但是您编写的 JavaScript 代码和您从中导入的代码不同的库将始终在单个线程中执行。异步操作会触发回调,回调会一个一个排队执行。


基本上执行此功能时会发生什么:


async function isThisLikeTwoThreads() {

 const a = slowFunction();

 const b = fastFunction();

 console.log(await a, await b);

}

执行slowFunction。执行fastFunction。当promise 和promise 已解决时,将其余代码 ( console.log(await a, await b))入队。在返回后以及可能的排队回调返回后,在同一线程中运行。假设和都返回承诺,这相当于:abconsole.log isThisLikeTwoThreadsslowFunctionfastFunction


function isThisLikeTwoThreads() {

 const a = slowFunction();

 const b = fastFunction();

 a.then(aResult => b.then(bResult => console.log(aResult, bResult)));

}


查看完整回答
反对 回复 2022-12-09
?
largeQ

TA贡献2039条经验 获得超7个赞

相似但不相同。Javascript 一次只会做“一件事”。它基本上是单线程的。也就是说,它可能看起来很奇怪,因为结果可能似乎以不同的顺序到达 - 异步和等待等功能加剧了这种情况。


例如,即使您以 70fps 的速度渲染后台进程,在可用于完成承诺或接收事件通知的渲染逻辑中也存在小间隙——正是在这些时刻,承诺完成,给人以多线程的错觉。


如果你真的想锁定浏览器,试试这个:


let a = 1;


while (a == 1){

    console.log("doing a thing");

}

你永远不会让 javascript 再次工作,而 chrome 或任何会扼杀你的脚本的东西。原因是当它进入该循环时——没有任何东西会再次接触它,不会呈现任何事件,也不会传递任何承诺——因此,单线程。


如果这是一个真正的多线程环境,您可以通过将变量更改为新值来从外部打破该循环。


查看完整回答
反对 回复 2022-12-09
  • 3 回答
  • 0 关注
  • 206 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信