「这是我参与2022首次更文挑战的第13天,活动详情查看:2022首次更文挑战」。
async和await是ES8新增的关键字。async用来声明一个函数是异步的。
async异步函数的写法
async异步函数可以有很多种写法。
async function foo1() {
}
const foo2 = async () => {
}
class Foo {
async bar() {
}
}
异步函数的执行流程
在异步函数中没有特殊代码的话,它跟普通函数的执行流程是一样的,默认会被同步执行。
async function foo() {
console.log('开始执行');
console.log('代码1');
console.log('代码2');
console.log('代码3');
console.log('结束执行');
}
console.log('1111');
foo()
console.log('2222');
异步函数和普通函数的区别
区别一:异步函数的返回值一定是个Promise
异步函数的返回值一定是个Promise,调用异步函数后,我们可以使用then方法,catch方法。
async function foo() {
console.log('开始执行');
console.log('中间代码');
console.log('执行结束');
}
const promise = foo()
promise.then(res => {
})
如果异步函数有返回值,那它会包裹到Promise的resolve中,此时res的值为异步函数返回的aaa。
async function foo() {
console.log('开始执行');
console.log('中间代码');
console.log('执行结束');
return 'aaa'
}
const promise = foo()
promise.then(res => {
console.log('then方法执行', res);
})
如果异步函数的返回值是Promise,那么它会决定Promise.resolve的状态。
async function foo() {
console.log('开始执行');
console.log('中间代码');
console.log('执行结束');
return new Promise((resolve, reject) => {
resolve('aaa')
})
}
const promise = foo()
promise.then(res => {
console.log('then方法执行', res);
})
如果异步函数的返回值是个对象并且实现了thenable,那么会由对象的then方法决定。
async function foo() {
console.log('开始执行');
console.log('中间代码');
console.log('执行结束');
return {
then: function(resolve, reject) {
resolve('aaa')
}
}
}
const promise = foo()
promise.then(res => {
console.log('then方法执行', res);
})
区别二:抛出异常
在普通函数中,我们抛出异常,调用函数的后续代码不执行。
function foo() {
console.log('代码开始执行');
console.log('中间代码');
throw new Error('错误信息')
console.log('执行结束');
}
foo()
console.log('后续代码');
执行该代码,我们可以看到foo()后面的代码没有执行。
那么如果是在异步函数中抛出异常会如何呢?
异步函数中抛出的异常,会作为异步函数返回的Promise的reject值的,而且后续代码会执行。
async function foo() {
console.log('代码开始执行');
console.log('中间代码');
throw new Error('错误信息')
console.log('执行结束');
}
foo().catch(err => {
console.log('err:', err);
})
console.log('后续代码');
区别3:异步函数中可以使用await关键字
如果在普通函数中使用await关键字,会报SyntaxError: await is only valid in async function的错误。
function foo() {
await 123
}
foo()
在异步函数中可以使用await,await后面通常跟表达式,表达式的返回值是个Promise。
await后面跟表达式
function requestData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(111)
}, 2000)
})
}
async function foo() {
const res1 = await requestData()
console.log('后面代码1', res1);
console.log('后面代码2');
console.log('后面代码3');
}
foo()
await后面的代码相当于requestData()生成的Promise对象中的then方法里面的代码,是等到await执行有结果后才开始执行。
await后面除了跟表达式,还可以跟普通值,thenable对象以及新的Promise。
await后面跟普通值
如果await后面是一个普通的值,那么会直接返回这个值。
async function foo() {
const res = await 123
console.log(res);
}
foo()
await后面跟thenable对象
如果await后面是一个thenable对象,那么会根据对象的then方法调用来决定后续的值。
async function foo() {
const res = await {
then: function(resolve, reject) {
resolve(123)
}
}
console.log(res);
}
foo()
await后面跟新的Promise对象
如果await后面跟一个新的Promise对象,那么会根据这个新的Promise对象的状态来决定后续的值。
async function foo() {
const res = await new Promise((resolve, reject) => {
resolve(123)
})
console.log(res);
}
foo()
要注意的是,如果await后面的表达式,是返回的Promise的reject的状态,那么会将这个reject结果直接作为函数Promise的reject值。
function requestData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(111)
}, 2000)
})
}
async function foo() {
const res = await requestData()
console.log('res', res);
}
foo().catch(err => {
console.log('err', err);
})