事件循环机制理解js的事件循环机制,能够很大程度的帮我们更深层次的理解平时遇到的一些很疑惑的问题简单版本下面来看一段代码,想想它的结果和你的结果是否一样 setTimeout(function() { console.log(1) }, 0) console.log(2) // 执行结果是 2 1我们可以将js的任务分为同步任务和异步任务, 按照这种分类js的执行机制如下任务执行队列分为同步任务队列和异步任务队列代码执行时,遇到同步代码,会被直接推入同步任务队列并依次执行遇到异步代码(如setTimeout、setInterval), 会被直接推入异步任务队列当同步任务队列执行完毕,这个时候异步任务队列的任务会被依次推入同步任务队列并依次执行所以上面的代码执行的时候, setTimeout()不会被立即执行,会被推到异步任务队列里面, 之后再执行console.log(2), 同步任务队列任务执行完毕之后,会去异步任务队列的任务会被依次推到 同步任务队列并执行终极版本下面来看一段代码,想想它的结果和你的结果是否一样 setTimeout(function() { console.log(1) }, 0) new Promise(function(resolve, reject) { console.log(2) resolve() }).then((res) => { console.log(3) }) console.log(4) // 执行结果是 2 4 3 1js按照准确的划分,应该将任务分为宏任务: 包括同步代码、setTimeout、setInterval微任务: 例如Promise的then方法注意: 一次事件循环,表示执行完一次宏任务队列、微任务队列(如果有),之后再进行第二次任务队列所以针对这种机制,js的一轮事件循环机制应该是这样的执行同步代码,依次推入宏任务队列并执行当遇到setTimeout、setInterval,会被推到下一次事件循环的宏任务队列在当前的事件循环中,如果遇到.then,会被当作微任务,被推入微任务队列,当宏任务队列执行完毕之后,再执行该队列的任务所以对于以上的代码执行流程如下:遇到setTimeout,被推到下一次的事件循环的宏任务队列当中由于new Promise是同步的,所以会被执行,这个时候console.log(2).then会被当作是微任务,被推到本轮事件循环的微任务队列继续执行同步代码,执行console.log(4)此时宏任务队列执行完毕, 继续执行微任务队列,此时console.log(3)此时微任务队列执行完毕, 进入下一次时间循环,console.log(1)async/awaitasync当我们在函数前使用async的时候,使得该函数返回的是一个Promise对象async function test() { return 1 // async的函数会在这里帮我们隐士使用Promise.resolve(1)}// 等价于下面的代码function test() { return new Promise(function(resolve, reject) { resolve(1) })}可见async只是一个语法糖,只是帮助我们返回一个Promise而已awaitawait表示等待,是右侧「表达式」的结果,这个表达式的计算结果可以是 Promise 对象的值或者一个函数的值(换句话说,就是没有特殊限定)。并且只能在带有async的内部使用使用await时,会从右往左执行,当遇到await时,会阻塞函数内部处于它后面的代码,去执行该函数外部的同步代码,当外部同步代码执行完毕,再回到该函数内部执行剩余的代码, 并且当await执行完毕之后,会先处理微任务队列的代码下面来看一个栗子: async function async1() { console.log( ‘async1 start’ ) await async2() console.log( ‘async1 end’ ) } async function async2() { console.log( ‘async2’ ) } console.log( ‘script start’ ) setTimeout( function () { console.log( ‘setTimeout’ ) }, 0 ) async1(); new Promise( function ( resolve ) { console.log( ‘promise1’ ) resolve(); } ).then( function () { console.log( ‘promise2’ ) } ) console.log( ‘script end’ ) 下面是在chrome浏览器上输出的结果使用事件循环机制分析:首先执行同步代码,console.log( ‘script start’ )遇到setTimeout,会被推入下一次的事件循环中的宏任务队列执行async1(), 它也是同步的,只是返回值是Promise,在内部首先执行console.log( ‘async1 start’ )然后执行async2(), 然后会打印console.log( ‘async2’ )从右到左会执行, 当遇到await的时候,阻塞后面的代码,去外部执行同步代码进入 new Promise,打印console.log( ‘promise1’ )将.then放入本次事件循环的微任务队列继续执行,打印console.log( ‘script end’ )外部同步代码执行完毕,接着回到async1()内部, 由于async2()其实是返回一个Promise, await async2()相当于获取它的值,其实就相当于这段代码Promise.resolve(undefined).then((undefined) => {}),所以.then会被推入微任务队列, 所以现在微任务队列会有两个任务。接下来处理微任务队列,打印console.log( ‘promise2’ ),后面一个.then不会有任何打印,但是会执行执行后面的代码, 打印console.log( ‘async1 end’ )进入第二次事件循环,执行宏任务队列, 打印console.log( ‘setTimeout’ )