有关 Javascript 的 event loop 和 async function,我始终没有弄明白。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
yazoox
V2EX    Javascript

有关 Javascript 的 event loop 和 async function,我始终没有弄明白。

  •  
  •   yazoox 2023-05-09 22:50:58 +08:00 1464 次点击
    这是一个创建于 886 天前的主题,其中的信息可能已经有所发展或是发生改变。

    就是这个异步函数到底是在立即执行(在后台另外一个线程中),然后把 callback 函数放到 event loop 的 task queue 中去,还是这个异步函数本身就被放到了 task queue 中去了,然后再下一次 event loop 中执行?

    如果是前者,Javascript 不是单线程的么?还有其它的线程执行异步函数?

    如果是后者,这个异步函数如果需要执行很长时间,比如 fetch 一个文件,那不是就会阻塞了 main thread ,页面就会卡住了?

    比如:

    const fetchData = () => { return new Promise((resolve, reject) => { fetch('https://api.example.com/data') .then(respOnse=> response.json()) .then(data => resolve(data)) .catch(error => reject(error)); }); }; fetchData() .then(data => console.log('Data:', data)) .catch(error => console.error('Error:', error)); 

    当 fetchData 被执行的时候,里面的fetch这个函数(异步函数),是被放到 backend thread 里面去执行了,然后它的 callback/then then(respOnse=> response.json()) 被会放 task queue 里面去?就是说除了 main thread ,还有很多其它 threads 了?( chatGPT 是这么解释的,说 Web API 都是由浏览器在 backend 后面开 thread 执行,但我不知道它是不是又在胡说八道......) 如果这个 fetch 需要花很多时间,在下一次 event loop 循环到的时候,还没有运行完,那它的 callback/then 咋整?

    所以,我这个 Javascript 的 event loop & async function 的关系犯迷糊了,绕不出来了。

    Fetch API is a promose-based https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

    jifengg
        1
    jifengg  
       2023-05-10 09:15:15 +08:00
    楼主,有些问题我没法回答你,但是有些还是可以说说。

    “Javascript 单线程”,是指,“你写的代码”,永远只有一处被执行。而 Javascript 引擎本身是多线程的,event loop 就是引擎用额外的线程来管理的,而且 event loop 里其实也分了“微任务( micro task )和宏任务( macro task )”

    另一个,“执行很长时间”你用 fetch 来举例是不恰当的,因为 fetch 也是异步函数( IO 异步),它不会阻塞 main thread ;要真正阻塞 js ,你必须用 cpu 密集型的代码才行(也就是让你的代码一直在被执行不停歇),比如 for(var i;i<100000000000;i++);
    CLMan
        2
    CLMan  
       2023-05-10 10:52:19 +08:00
    1. 应该是后者吧,`fetch`是个 Promise API ,不会阻塞 main thread 。

    2. 真要完全弄清楚的话,你始终在 Javascript 层面思考是没用的,因为计算机软件是分层的,每层向上提供封装,特别是 io 、线程之类的,并没有完全屏蔽底层并提供完备抽象的封装。你要去研究浏览器实现,去研究 OS API 实现,去研究硬件实现,但没有相关知识储备的话,这个过程效率极低,量力而行。
    hsir
        3
    hsir  
       2023-05-21 14:17:41 +08:00
    你打印一下 fetch.toString(),会得到 function fetch() { [native code] }。这个 API 调用后就是浏览器自己的某个其他 thread 去请求了,进行到这一步,JS 线程不会等,会继续做其他的事情。直到浏览器请求完成,拿到 fetch result 后,主动把这个 result 告诉 JS ,于是 JS 就可以跑你的 then 逻辑了。
    daolanfler
        4
    daolanfler  
       2023-05-25 17:39:19 +8:00
    <iframe width="560" height="315" src="https://www.youtube.com/embed/8aGhZQkoFbQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
    daolanfler
        5
    daolanfler  
       2023-05-25 17:40:33 +08:00
    @daolanfler


    这两个视频看一下就能有个概念了
    ChanKc
        6
    ChanKc  
       2023-05-28 00:38:52 +08:00 via Android
    1 楼说的不对,js 就是单线程的,除非你用 worker 。event loop 就是一个线程的事情。
    fetch 比较复杂,不建议你用 fetch 去理解 event loop 。
    fetch 实际上会调起一个你 js 代码无法控制的线程(下面简称网络线程)去执行 http 请求。直到 http 响应前,任务队列里都是空的。响应后网络线程会通知主线程,主线程执行 then(someTask),会把 someTask 放入队列(但不会马上执行,直到下一次队列检测时)。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1120 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 18:01 PVG 02:01 LAX 11:01 JFK 14:01
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86