1.浏览器中的线程有以下几种:
- js执行线程
- GUI渲染线程
- 事件监听线程
- 计时器计时线程
- 网络通信线程
2.如何理解js单线程?
之所以说js单线程,是因为它的执行引擎只有一个线程,并且不会在执行期间开启新的线程。而并非是指浏览器单线程。
3.js执行栈
js线程执行任务时,会创建js执行栈。同步任务直接推入执行栈中执行,异步任务推入事件队列中,注册回调函数。当执行栈空闲时,js会去事件队列中读取事件当初注册的回调函数,到执行栈中,并执行函数。
4.事件队列划分
- 宏队列:script, settimeout,ajax请求,dom事件
- 微队列:Promise.then、MutationObserver
当执行栈空闲时,js首先会将微队列中的所有微任务执行完,再去执行宏队列中的宏任务。
一轮循环是这样的:当js执行时,先执行宏任务,遇到微任务,则推入微队列,并注册回调函数。当所有宏任务执行完后,会读取微任务注册的回调函数到执行栈中执行。执行完后。继续下一轮循环
看下面这个示例:
setTimeout(function () {
console.log('three');
}, 0);
Promise.resolve().then(function () {
console.log('two');
});
console.log('one');
结果:
// one
// two
// three
分析:
-
首先整段代码可以看做是
宏任务
, -
当js执行时,遇到
setTimeout
,它是宏任务,则放入宏队列,等待本轮执行完后,在一轮循环中执行。然后遇到了promise的then,则被推入微队列。 -
接着,打印
one
。好了,到此,本轮所有的宏任务已经执行完毕,但是,本次循环并未结束。 -
然后,js去微队列中读取then注册的回调函数执行,打印
two
。 -
注意了!!!到此,本轮所有任务执行完毕,本次事件循环结束了。
-
接着,开启下一轮循环,执行settimeout,打印
three
。所以,输出结果为:
one
two
three