跳到主要内容

认识

一、认识


async/await 也是异步编程的一种解决方案,是 Generator 函数的语法糖,同时基于Promiseasync 函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已。主要的作用是 用同步的方式,执行异步的操作

async, 在函数前加上 async 关键字,表示该函数内部可能包含异步操作。无论函数内部返回什么,都会被自动包装成一个 Promise。如果函数返回的是一个值,则返回一个立即 resolvePromise; 如果返回的是一个 Promise, 则直接返回该 Promise异常处理, 在 async 函数中抛出的异常, 会导致返回的 Promise 被拒绝, 可以通过 .catch()try/catch 捕获错误。

await, 当执行到 await 表达式时,首先会对其右侧的表达式进行同步求值。如果该表达式返回的是一个非 Promise 值,它会被自动包装为一个立即 resolvePromise。如果返回的是一个 Promise,则直接使用该 Promise。一旦右侧 Promise 状态改变(resolvereject), await 后面的语句会被放入微任务队列中,等待当前同步任务和其他微任务执行完毕后,再恢复 async 函数的执行。这种机制与调用 .then() 很相似,可以理解为 await 将后续代码隐式地放到了对应 Promise.then() 回调中。

async/await 异常捕获机制: 在 async/await 的模式下, 无论是同步代码中直接抛出的错误, 还是 await 表达式等待的 Promise 被拒绝(即出错), 都会导致整个 async 函数中止执行, 并且这个函数返回的 Promise 会变成 reject 状态, 错误对象会传递给调用者的 .catch() 或通过 try/catch 捕获。

二、语法


function promise1(){
return new Promise((resolve,reject)=>{

});
}

async function async1(){
return 1
}

async function async2(){
try{
const result1 = await promise1();
console.log("result1", result1)
const result2 = await async2();
console.log("result2", result2);
}catch(error){
console.log("error", error);
}
}

三、检测


描述: 如何判断传入的函数是否标记了 async

3.1 Symbol.toStringTag

function isAsyncFunction(func) {
return func[Symbol.toStringTag] === "AsyncFunction";
}

console.log("function >>> ", isAsyncFunction(() => {}));
console.log("async function >>> ", isAsyncFunction(async () => {}));
console.log("function Promise >>> ", isAsyncFunction(() => {return new Promise()}));

3.2 Object.prototype.toString.call

function isAsyncFunction(func) {
return Object.prototype.toString.call(func) === "[object AsyncFunction]";
}

console.log("function >>> ", isAsyncFunction(() => {}));
console.log("async function >>> ", isAsyncFunction(async () => {}));
console.log("function Promise >>> ", isAsyncFunction(() => {return new Promise()}));

四、调用


4.1 函数

4.2 顶层

早期的语法规定是,await命令只能出现在 async 函数内部,否则都会报错。

五、问题


5.1 async vs generator

  • 内置执行器: Generator 函数的执行必须靠执行器,所以才有了co模块,而async函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行。

  • 更好的语义: asyncawait,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。

  • 更广的适用性: co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolvedPromise 对象)。

  • 返回值是 Promise: async 函数返回值是 Promise 对象,比 Generator 函数返回的 Iterator 对象方便,可以直接使用 then() 方法进行调用

参考资料


你不知道的 async、await 魔鬼细节