JS线程
操作系统
进程和线程
操作系统的工作方式
浏览器中的JS线程
用浏览器执行,进程就是浏览器;
用NodeJS执行,进程就是单开的一个NodeJS进程;
比如发送网络请求,JS线程执行到这里,就丢给浏览器的其他线程去和服务器沟通(多次握手,建立TCP链接,传输数据等),处理完了再给JS线程继续处理。
那么这些任务,会放在JS的事件循环中处理,里面有个队列(见下)
==================
事件循环
浏览器的事件循环 Event Loop
浏览器的事件队列
因此 微任务 > 宏任务
面试题1
setTimeout(function () {
console.log("setTimeout1");
new Promise(function (resolve) {
resolve();
}).then(function () {
new Promise(function (resolve) {
resolve();
}).then(function () {
console.log("then4");
});
console.log("then2");
});
});
new Promise(function (resolve) {
console.log("promise1");
resolve();
}).then(function () {
console.log("then1");
});
setTimeout(function () {
console.log("setTimeout2");
});
console.log(2);
queueMicrotask(() => {
console.log("queueMicrotask1")
});
new Promise(function (resolve) {
resolve();
}).then(function () {
console.log("then3");
});
次数 | main scripts | 微任务 | 宏任务 |
---|---|---|---|
第一次执行, 遇到setTimeout加到宏任务队列; 遇到new Promise 先执行里面的,然后把then加到微任务队列; 遇到普通代码直接执行; 遇到queueMicrotask 放到微任务队列; |
|||
第二次执行, 清空微任务队列 |
|||
第三次执行, 执行宏任务队列里的第一个setTimeout, 把里面的new Promise加到微任务队列 |
|||
第四次执行, 执行完微任务队列, 遇到then再加入微任务队列 |
|||
第五次执行, 执行完微任务队列, 再执行下一个setTimeout |
|||
最终结果 |
面试题2
1、先执行foo( )
2、打印1111111
3、执行await 里面的bar( )
4、打印22222
5、把new Promise放入微任务队列,包括下面的33333
6、执行444444
7、然后执行微任务队列,输出33333
NodeJS的事件循环
libuv是一个库,用C语言编写
文件IO(Input / Output):比如文件的读取、写入,操作数据库等
以前的JS是没有这样的能力,但有了Libuv这个库后,这部分的操作会交由这个库操作,操作完后返回给JS引擎