单线程和异步
JS是单线程的(无论在浏览器还是在nodejs)
浏览器中JS执行和DOM渲染公用一个线程
异步
宏任务和微任务
宏任务,如setTimeout setInterval 网络请求
微任务,如Promise async/await
微任务在下一轮DOM渲染前执行,宏任务在DOM渲染之后执行
nodejs异步
Nodejs同样使用ES语法,也是单线程,也需要异步
异步任务也分:宏任务 + 微任务
但是,他的宏任务和微任务,分不同的类型,有不同的优先级
nodejs宏任务类型和优先级(从上到下)
Timers —— setTimeout setInterval
I/O —— callbacks - 处理网络流,TCP的错误回调
Idle,prepare —— 闲置状态(nodejs内部使用)
Poll轮调 —— 执行 poll 中的I/O队列
check检查 —— 存储 setImmediate 回调
close callbacks —— 关闭回调,如socket.on(‘close’)
nodejs 微任务类型和优先级
包括:promise, async/await,process.nextTick
注意,process.nextTick 优先级最高
nodejs event loop(事件循环**)**
执行同步代码
执行微任务(process.nextTick优先级最高)
按顺序执行6个类型的宏任务(每个人物结束时都执行当前的微任务)
答案
浏览器和nodejs的event loop 流程基本相同
nodejs宏任务和微任务分类型,有优先级
注: 在开发过程中如果有需求,推荐使用setTmmediate代替process.nextTick
代码演示:
event loop
<script> console.log('start') setTimeout(() => { console.log(timeout) }) Promise.resolve().then(() => { console.log('promise then') }) console.log('end') // ajax(url, fn) // 假设 300ms // Event Loop 继续监听 // 宏任务 MarcoTask Queue // () => { // console.log(timeout) // } // fn // 1000ms 后,fn // DOM 渲染 // 微任务 MicroTask Queue // () => { // console.log('promise then') // } // const p = document.createElement('p') // p.innerHTML = 'new paragraph' // document.body.appendChild(p) // const list = document.getElementsByTagName('p') // console.log('length---', list.length) // console.log('start') // // 渲染之后 // setTimeout(() => { // const list = document.getElementsByTagName('p') // console.log('length on timeout', list.length) // alert('阻塞 timeout') // }) // // 渲染之前 // Promise.resolve().then(() => { // const list = document.getElementsByTagName('p') // console.log('length on promise', list.length) // alert('阻塞 promise') // }) // console.log('end')
</script>
nodejs异步(执行方式)
console.log('start')setImmediate(() => { console.log("setImmediate")})setTimeout(() => { console.log('timeout')})Promise.resolve().then(() => { console.log('Promise then')})process.nextTick(() => { console.log('nextTick')})console.log('end')