JavaScript消息队列是否可被阻塞?Web API线程入队相关技术疑问
核心结论
Web API线程完全可以在JavaScript线程执行函数的同时,将回调消息加入消息队列,不存在需要等待的情况。
具体细节拆解
消息队列的归属与线程安全实现
消息队列并不是JavaScript线程的私有资源,它是由浏览器/Node.js这类宿主环境维护的线程安全数据结构。宿主环境会通过锁、原子操作等机制,保证多个线程(JS线程、多个Web API线程)对队列的读写操作不会冲突。比如当AJAX请求完成、setTimeout计时结束时,对应的Web API线程会直接把回调函数封装成消息,原子性地插入到消息队列中,这个过程和JS线程是否在执行代码完全无关。JS线程的执行逻辑不影响入队
JavaScript线程的执行遵循“调用栈清空后才会处理消息队列”的规则——只要调用栈里还有未执行完的函数,事件循环就不会去读取消息队列。但这并不影响Web API线程往队列里加消息,哪怕队列已经被塞满,Web API线程的入队操作也不会被阻塞,宿主会负责处理队列的存储和同步。不存在Web API线程等待入队的场景
所有Web API的回调入队操作都是非阻塞的,Web API线程完成自身任务后(比如网络请求拿到响应),只需要把回调扔进队列就可以结束自身工作,不需要等待JS线程处理这个消息。举个常见的例子:你写了一个需要10秒才能执行完的同步函数,同时在函数里调用了setTimeout(() => console.log('timeout'), 100),Web API线程会在100毫秒到点时,直接把这个回调放进消息队列,然后就没事了,直到10秒后JS线程的长函数执行完,事件循环才会取出这个回调执行。
内容的提问来源于stack exchange,提问作者ricale

