基础定义 promise Promise 对象是由关键字 new 及其构造函数来创建的。 该构造函数会把一个叫做“处理器函数”(executor function)的函数作为它的参数。 这个“处理器函数”接受两个函数——resolve 和 reject ——作为其参数。 当异步任务顺利完成且返回结果值时,会调用 resolve 函数; 而当异步任务失败且返回失败原因(通常是一个错误对象)时,会调用reject 函数
async 当调用一个 async 函数时,会返回一个 promise 对象 当这个异步函数返回一个值时,async 通过 Promise.resolve() 将这个值封装成 promise 对象 当这个异步函数没有返回值时,会返回 Promise.resolve(undefined) 当 async 函数抛出异常时,Promise 的 reject 方法也会传递这个异常值 async 函数中可能会有 await 表达式,这会使 async 函数暂停执行,等待 Promise 的结果出来,然后恢复async函数的执行并返回解析值(resolved 注意:Promise 的特点——无等待,所以在没有 await 的情况下执行 async 函数,它会立即执行,返回一个 Promise 对象,并且,绝不会阻塞后面的语句。这和普通返回 Promise 对象的函数并无二致
await await 操作符用于等待一个Promise 对象。它只能在异步函数 async function 中使用。 语法:[return_value] = await expression; expression 是一个 Promise 对象或者任何要等待的值。返回 Promise 对象的处理结果。如果等待的不是 Promise 对象,则返回该值本身。 await 表达式会暂停当前 async function 的执行,等待 Promise 处理完成。 若 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的值,继续执行 async function。 若 Promise 处理异常(rejected),await 表达式会把 Promise 的异常原因抛出。 另外,如果 await 操作符后的表达式的值不是一个 Promise,则返回该值本身。 注意重点:很多人以为await会一直等待之后的表达式执行完之后才会继续执行后面的代码, 实际上await是一个让出线程的标志。await后面的函数会先执行一遍,然后就会跳出整个async函数来执行后面js栈的代码。 等本轮事件循环执行完了之后又会跳回到async函数中等待await后面表达式的返回值 如果返回值为非 promise 则继续执行 async 函数后面的代码,否则将返回的 promise 放入 promise 队列(Promise的Job Queue)
执行机制 首先我们知道js是单线程语言,任务可以分为同步任务,异步任务,当然也可以分为宏任务,微任务。 任务 举例 宏任务 整体js代码、setTimeout、setInterval等 微任务 Promise,process.nextTick等 执行机制(event loop) 在这里插入图片描述
同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。 当指定的事情完成时,Event Table会将这个函数移入Event Queue。 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。 上述过程会不断重复,也就是常说的Event Loop(事件循环)。 事件循环、宏任务、微任务关系图 在这里插入图片描述
实例讲解 下面举个栗子:
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');1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 打印结果为:
script start async1 start asynic2 promise1 script end async1 end promise2 setTimeout1 2 3 4 5 6 7 8 具体解释:
整体代码作为宏任务(同步任务)从上至下执行,首先打印script start 遇到setTimeout异步任务,那么将其回调函数注册后分发到宏任务Event Queue 接下来遇到async function,打印async1 start 执行await后面的async2(),打印出asynic2,产生一个微任务,分发到Event Queue,等待返回一个promise.resolve(undefined) new Promise立即执行打印promise1,产生一个微任务,分发到Event queue,等待返回一个promise.resolve() 打印script end,同步任务首次结束,下面执行异步任务 先看Event queue 队列里面是否有微任务,如果存在首先执行微任务,打印async1 end 然后继续打印 promise2 最后打印出event queue 队列里面的宏任务,打印出 setTimeout 尝试解释下面这段代码吧
async function testSometing() { console.log("执行testSometing"); return "testSometing"; } async function testAsync() { console.log("执行testAsync"); return Promise.resolve("hello async"); } async function test() { console.log("test start..."); const v1 = await testSometing(); console.log(v1); const v2 = await testAsync(); console.log(v2); console.log(v1, v2); } test(); var promise = new Promise( (resolve) => { console.log("promise start.."); resolve("promise"); } ); promise.then((val)=> { console.log(val) }); console.log("test end...")