关于js中事件循环、同步异步、宏任务和微任务存在的时候函数执行顺序的简单理解
讲述目的:本文章针对JS萌新,是要用最简单的解释让读者能够判断在函数语句的执行顺序,不涉及关于js更深层的理解和探讨也不花费精力讲解js为什么会将执行任务有这些区分,只讨论任务的执行顺序,保护读者不被各种概念绕晕,大神可绕道。
讲述思路:
1.简单理解同步异步、宏任务和微任务
2.执行顺序判断方法
3.简单实例分析
4.稍复杂点的实例分析
正文开始:
1.简单理解同步异步、宏任务和微任务
js是单线程的,所有的任务都要排队挨个执行,就好比做保健(执行js代码),保健师傅只有一个(单线程),顾客(js代码)需排队享受服务,排队的顺序按照顾客的种类(同步异步、宏任务微任务)和顾客到店顺序(在代码中的位置)执行;
同步与异步、宏任务和微任务分别是函数两个不同维度的描述。
异步任务:setTimeout和setInterval、ajax、事件绑定等
同步任务:除了异步任务外的所有任务
微任务:process.nextTick和 Promise后的theny语句和catch语句等
宏任务:除了微任务以外的所有任务
2.执行顺序判断方法
先同步再异步,在此基础上先宏任务再微任务
3.简单实例分析
1 setTimeout(function () { 2 new Promise(function (resolve, reject) { 3 console.log('异步宏任务promise'); 4 resolve(); 5 }).then(function () { 6 console.log('异步微任务then') 7 }) 8 console.log('异步宏任务'); 9 }, 0) 10 new Promise(function (resolve, reject) { 11 console.log('同步宏任务promise'); 12 resolve(); 13 }).then(function () { 14 console.log('同步微任务then') 15 }) 16 console.log('同步宏任务')
结果
分析:setTimeout是异步任务,虽然他在0秒后执行但仍排在队列的后面,因此其中的代码全部靠后执行;new Promise是同步任务同时也是主任务,因此第一行先打印'同步宏任务promise',then是微任务所以靠后执行,先执行第16行代码,之后再执行第13行的then语句,因此第二行输出为'同步宏任务',第三行为'同步微任务then';接下来执行setTimeout中的语句,then因为是微任务所以在第8行执行完成后再执行。
4.稍复杂点的实例分析
1 setTimeout(() => { 2 console.log('异步1任务time1'); 3 new Promise(function (resolve, reject) { 4 console.log('异步1宏任务promise'); 5 setTimeout(() => { 6 console.log('异步1任务time2'); 7 }, 0); 8 resolve(); 9 }).then(function () { 10 console.log('异步1微任务then') 11 }) 12 }, 0); 13 console.log('主线程宏任务'); 14 setTimeout(() => { 15 console.log('异步2任务time2'); 16 17 }, 0); 18 new Promise(function (resolve, reject) { 19 console.log('宏任务promise'); 20 // reject(); 21 resolve(); 22 }).then(function () { 23 console.log('微任务then') 24 }).catch(function () { 25 console.log('微任务catch') 26 }) 27 console.log('主线程宏任务2');
本例中需注意第9行的then是在第14行的setTimeout之前执行的,而第5行的setTimeout在第14行之后执行。也就是在一个异步任务代码块中,会先执行完所有同步语句(包括宏任务和微任务),然后去执行整个代码中的同级别的异步任务,而第5行的setTimeout因是第二层异步语句,会被放到之后才执行。
执行结果为