事件循环的概念:
因为js是单线程的。所以js是从上至下按顺序运行下去的,顺序执行代码,那么,如果js代码中间向后台发送一个ajax请求,就要等到请求等到结果后才会继续向下执行。如果请求耗时过长,或者请求报错,会导致用户体验不好。因此,就有了同步任务、异步任务的区别。
同步任务和异步任务在js中是如何执行的呢?js的代码运行会形成一个主线程和一个任务队列。主线程会从上到下一步步执行我们的js代码,形成一个执行栈。同步任务就会被放到这个执行栈中依次执行。而异步任务被放入到任务队列中执行,执行完就会在任务队列中打一个标记,形成一个对应的事件。当执行栈中的任务全部运行完毕,js会去提取并执行任务队列中的事件。这个过程是循环进行的,这就是我们今天想要了解的event loop
因为js的event loop机制,所以大家不要认为setTimeOut设置的事件到了延迟时间就是被执行。如果你的执行栈任务没有被全部执行完,清空。setTimeOut事件执行的时间很有可能是要大于你设置的延时参数。
宏任务微任务:
异步任务之间是有执行优先级的区别的。不同的异步任务会被分为两类,微任务和宏任务
宏任务: 需要多次事件循环才能执行完,事件队列中的每一个事件都是一个宏任务。
常见的宏任务:定时器,延时器,ajax, 交互事件
微任务: 微任务是一次性执行完的。微任务通常来说是需要在当前task执行结束后立即执行的任务,例如对一些动作做出反馈或者异步执行任务又不需要分配一个新的task,这样便可以提高一些性能。
常见的微任务:promise.then(), process.nextTick , MutationObserver
宏任务中包含微任务时,按照顺序循环执行
new Promise((reslove,reject)=>{ console.log("romise start") reslove("data") }).then((res)=>{ console.log(res) }) setTimeout(()=>{ console.log("settimeout start") new Promise((reslove,reject)=>{ console.log("romise1111 start") reslove("data romise11") }).then((res)=>{console.log(res)}) console.log("settimeout end") },0) setTimeout(()=>{ console.log("settimeout222 start") new Promise((reslove,reject)=>{ console.log("romise2222 start") reslove("data romise2222") }).then((res)=>{console.log(res)}) console.log("settimeout222 end") },0) console.log(10000)
以上代码执行效果如下:
romise start
10000
data首先程序进入到代码块执行scrit主线程任务 romise start , 10000,然后执行了Promise.then() // data
settimeout start
romise1111 start
settimeout end
data romise11延时器属于宏任务,但是延时器里面还有同步任务和微任务,首先执行完了同步任务 settimeout start , romise1111 start , settimeout end,然后执行微任务。
第一个宏任务执行完毕了,接着开始执行第二个宏任务。
settimeout222 start
romise2222 start
settimeout222 end
data romise2222
微任务中混合宏任务 相互混合
{ console.log(1); setTimeout(() => { console.log(2); }) new Promise((resolve) => { console.log(3) resolve() }).then(() => { setTimeout(() => { console.log(4); }) }).then(() => { console.log(5) }) console.log(6) setTimeout(() => { console.log(7) new Promise(resolve => { console.log(8) setTimeout(() => { console.log(9) }) resolve() }).then(() => { console.log(10) }) }, 500) new Promise(resolve => { console.log(11) resolve() }).then(() => { console.log(12) setTimeout(() => { console.log(13) }, 0) }) console.log(14) // 1 3 6 11 14 主线程 // 12 5 // 宏任务 2 4 13 7 8 10 9 }