理解js
的事件循环机制,可以很大程度的帮咱们更深层次的理解平时遇到的一些很疑惑的问题chrome
下面来看一段代码,想一想它的结果和你的结果是否同样promise
setTimeout(function() { console.log(1) }, 0) console.log(2) // 执行结果是 2 1
咱们能够将js
的任务分为同步任务和异步任务, 按照这种分类js
的执行机制以下浏览器
setTimeout、setInterval
), 会被直接推入异步任务队列 因此上面的代码执行的时候, setTimeout()
不会被当即执行,会被推到异步任务队列里面, 以后再执行console.log(2)
, 同步任务队列任务执行完毕以后,会去异步任务队列的任务会被依次推到 同步任务队列并执行异步
下面来看一段代码,想一想它的结果和你的结果是否同样async
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 1
js
异步任务按照准确的划分,应该将任务分为函数
setTimeout
、setInterval
Promise.then
方法。注意new Promsie()
的时候是同步,当即执行。注意: 如今有三个队列: 同步队列(也称执行栈)、宏任务队列、微任务队列spa
因此针对这种机制,js
的事件循环机制应该是这样的code
setTimeout、setInterval
,会被推到宏任务队列 .then
,会被看成微任务,被推入微任务队列console.log(1); setTimeout(() => { console.log('setTimeout'); }, 0); let promise = new Promise(resolve => { console.log(3); resolve(); }).then(data => { console.log(100); }).then(data => { console.log(200); }); console.log(2);
因此对于以上的代码执行流程以下:对象
setTimeout
是宏任务,会先放到宏任务队列中。new Promise
是当即执行的,因此会先输出3。Promise.then
是微任务,会依次排列到微任务队列中,继续向下执行输出2。setTimeout
。当咱们在函数前使用async
的时候,使得该函数返回的是一个Promise
对象队列
async function test() { return 1 // async的函数会在这里帮咱们隐士使用Promise.resolve(1) } // 等价于下面的代码 function test() { return new Promise(function(resolve, reject) { resolve(1) }) }
可见async
只是一个语法糖,只是帮助咱们返回一个Promise
而已
await
表示等待,是右侧「表达式」的结果,这个表达式的计算结果能够是 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' )