js 事件循环机制
线程和进程
线程:线程是CPU调度的最小单位
进程:进程是资源分配的最小单位
背景:进程和线程不是同一个层面的概念,线程是进程的一部分,线程主抓中央处理器执行代码的过程,其余的资源的保护和管理由整个进程去完成
任务队列,任务分类
定义:所有的任务可以分为同步任务和异步任务。同步任务,立即执行的任务,同步任务会直接进入到主线程中执行;异步任务,异步任务会通过任务队列的机制(先进先出)来进行协调
异步任务:宏任务(macro-task)和微任务(micro-task)
cmd-markdown-logo cmd-markdown-logo执行顺序:先执同步任务,再执行异步任务;先执行微任务,再执行宏任务
宏任务(macro-task) | 微任务(micro-task) |
---|---|
script | promise.[ then/catch/finally ]((非new Promise)) |
setTimeout | process.nextTick(Node.js 环境) |
setInterval | MutaionOberver(浏览器环境) |
setImmediate(Node.js 环境) | Object.observe |
IO操作 | x |
UI交互事件 | x |
postMessage | x |
MessageChannel | x |
事件循环
定义:主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。不断重复的过程就是Event Loop (事件循环)
js是单线程
浏览器是多进程的,浏览器每个tab标签都代表一个独立的进程,其中浏览器渲染进程(浏览器内核)属于浏览器多进程中的一种,主要负责页面渲染,脚本执行,事件处理等。其包含的线程有:GUI渲染线程(负责渲染页面,解析HTML,CSS构成DOM树)、JS引擎线程、事件触发线程、定时器触发线程、http请求线程等主要线程
注意:js设计为单线程还是跟他的用途有关,如果js设计为多线程,那么同时修改和删除同一个dom,浏览器该如何执行。
js为什么需要异步,如果js中不存在异步,只能自上而下执行,如果上一行解析时间很长,那么下面的代码就会被阻塞。导致用户体验很差
练习题
1、
async function async1() {
console.log('async1 start');
await async2();
console.log('asnyc1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(() => {
console.log('setTimeOut');
}, 0);
async1();
new Promise(function (reslove) {
console.log('promise1');
reslove();
}).then(function () {
console.log('promise2');
})
console.log('script end');
正确答案
script start
async1 start
async2
promise1
script end
asnyc1 end
promise2
setTimeOut
2、
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
正确答案:1,7,6,8,2,4,3,5,9,11,10,12
async/await
带async
关键字的函数回返回一个promise
对象,如果里面没有await
,执行起来等同于普通函数;如果有await
,async
函数并没有很厉害
await关键字要在async关键字函数的内部,await写在外面会报错;await如同他的语意,就是在等待,等待右侧的表达式完成。此时的await会让出线程,阻塞async内后续的代码,先取执行async外的代码。等外面的同步代码执行完毕,才会执行里面的后续代码。就算await的不是promise对象,是一个同步函数,也会等这样的操作