Appearance
浏览器事件循环
本节目标:理解“浏览器事件循环”的核心思路,并能把它用于实际开发或面试表达。
说明:原 OneNote 中有图片引用,但图片未包含在导出目录中;本页保留了可用的文字与代码内容。 事件环为了实现
js的异步概念
js是“单线程” (主线程)的, 我们在写代码的时候 setTimeout ajax
进程:计算机分配任务的最小单位 (不是按照线程分配的) 进程里包含多个线程
浏览器是由多个进程组成的
EventLoop解决的是 js执行时可能会调用异步方法,这些方法是怎样调度执行的
js执行的时候 会从上到下执行,遇到函数会创建执行上下文放入到执行栈中,执行完毕后会出栈 执行时可能会发生异步事件--\>内部会调用浏览器Api- 当我们执行上下文栈都执行完毕后, 等会可能
api执行完成或者时间到达,会被我IE互道一个事件“队列”、消息“队列”; - 不停的扫描队列,将队列里的任务拿出来放到上下文栈中执行:事件循环线程是专门干这件事的,检测当前执行栈是否为空,如果为空,从事件队列中取出一个来执行
setTimeout宏任务; - 当代码执行时还会有一些任务,
promise为例,微任务,每次执行宏任务的时候 都会单独创建一个微任务“队列”; - 微任务在执行完毕后,浏览器会检测是否要重新渲染,浏览器有刷新频率大约
16.6ms; - 每次循环一次都会执行一个宏任务,并清空对应的微任务队列,每次循环完毕后,都要看是否要渲染,如果需要渲染才渲染;
宏任务有哪些:
script脚本- 界面渲染也是宏任务
setTimeoutsetInterval;postMessage;MessageChannel;Node中的setImmediate- 事件
ajax
微任务有哪些:
promise.thenmutationObserver
Node 中的 Process.nextTick等微任务中在执行时再生成微任务,会在本轮直接清空 console.log('abc') // [s1
,s2]
setTimeout(()=\> {
console.log('abc');
},1000);
setTimeout(()=\> {
console.log('bcd');
},500);
1.浏览器的进程
- 每一个页卡都是进程
(互不影响) - 浏览器也有一个主进程
(用户界面) - 渲染进程 每个页卡里 都有一个渲染进程
(浏览器内核) - 网络进程 (处理请求)
GPU进程3d绘制- 第三方插件的进程
2. 渲染进程(包含着多个线程)
GUI渲染线程 (渲染页面的)js引擎线程和页面渲染线程是互斥的;- 事件触发线程:独立的线程
EventLoop - 事件线程也是一个独立的线程,如:
click、setTimeout、ajax
# 3.宏任务,微任务
- 宏任务 宿主环境提供的异步方法 都是宏任务
script ui渲染 - 微任务 语言标准提供
promise mutationObserver
# 4.微任务和GUI渲染
<script> document.body.style.background = 'red'; console.log(1) Promise.resolve().then(()=>{ console.log(2) document.body.style.background = 'yellow'; }) console.log(3);</script>
# 5.事件任务
<script> button.addEventListener('click',()=>{ console.log('listener1'); Promise.resolve().then(()=>console.log('micro task1')) }) button.addEventListener('click',()=>{ console.log('listener2'); Promise.resolve().then(()=>console.log('micro task2')) }) button.click(); // click1() click2()</script>
# 6.定时器任务
<script> Promise.resolve().then(() => { console.log('Promise1') setTimeout(() => { console.log('setTimeout2') }, 0); }) setTimeout(() => { console.log('setTimeout1'); Promise.resolve().then(() => { console.log('Promise2') }) }, 0);</script>
# 7.任务执行面试题
console.log(1);async function async () { console.log(2); await console.log(3); console.log(4)}setTimeout(() => { console.log(5);}, 0);const promise = new Promise((resolve, reject) => { console.log(6); resolve(7)})promise.then(res => { console.log(res)})async (); console.log(8);掌握Vue中nextTick原理
宏任务每执行一个,微任务队列清空; 宏任务队列只有一个,微任队列只有一个,但会多次清空;清空后再加入新任务,相当于多个微任务队列一样;
当执行栈中的同步任务执行完后,就会去任务队列中拿一个宏任务放到执行栈中执行,执行完该宏任务中的所有微任务,再到任务队列中拿宏任务,即一个宏任务、所有微任务、渲染、一个宏任务、所有微任务、渲染...(不是所有微任务之后都会执行渲染),如此形成循环,即事件循环(EventLoop)
但浏览器特殊的规定,如果promise 返回了一个promise,会额外再开辟一个异步方法(相当于又多了一次then)
重看promsie 解题 4/4号
> 来自
<http://www.zhufengpeixun.com/jg-vue/node/async-2.html#_6-%E5%AE%9A%E6%97%B6%E5%99%A8%E4%BB%BB%E5%8A%A1>