就是这个异步函数到底是在立即执行(在后台另外一个线程中),然后把 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
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++); |
2
CLMan 2023-05-10 10:52:19 +08:00
1. 应该是后者吧,`fetch`是个 Promise API ,不会阻塞 main thread 。
2. 真要完全弄清楚的话,你始终在 JavaScript 层面思考是没用的,因为计算机软件是分层的,每层向上提供封装,特别是 io 、线程之类的,并没有完全屏蔽底层并提供完备抽象的封装。你要去研究浏览器实现,去研究 OS API 实现,去研究硬件实现,但没有相关知识储备的话,这个过程效率极低,量力而行。 |
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 逻辑了。
|
4
daolanfler 2023-05-25 17:39:19 +08: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>
|
5
daolanfler 2023-05-25 17:40:33 +08:00
|
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 放入队列(但不会马上执行,直到下一次队列检测时)。 |