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引擎


NodeJS的事件队列

















































