参考文章:深入理解async和await
1. async的作用
先看下这两个函数:
// 函数1
async function Test() {
return 'return test value'
}
Test(); // Promise {<fulfilled>: 'return test value'}
// 函数2
function Test2() {
return new Promise(resolve => {
resolve('return test2 value')
})
}
Test2(); // Promise {<fulfilled>: 'return test2 value'}
可以看到:async函数返回的是一个Promise对象,如果在函数中return一个直接量,async会把这个直接量通过Promise.resolve()封装成Promise对象
2. await在等什么呢?
首先我们要知道,await是一个用于组成表达式的运算符,await它可以等任何函数返回值,不只是Promise对象,它会根据等到的值做不同的事情
- 等到的不是Promise对象,表达式的值就是返回值
- 等到了Promise对象,await先阻塞后面的代码,等待Promise对象resolve,然后将resolve的值作为表达式的结果
3. async/await的优势
先来了解一句话
Promise通过.then链来解决多层回调的问题,而async/await是用来进一步优化它的
我们来假设有这样一个业务逻辑,需要在一所学校里面找到一名学生
- 第一步,找到他在哪个年级(以下都是异步操作)
function findGrade(name) {
return new Promise(resolve => {
setTimeout(() => {
resolve('高二'); // 假设根据name找到的结果为:"高二"
}, 1000)
})
}
- 第二步,找到他在哪个班级
function findClassName(grade) {
return new Promise(resolve => {
setTimeout(() => {
resolve('高二(3)班'); // 假设根据grade找到的结果为:"高二(3)班"
}, 1000)
})
}
- 第三步,找到班级教室
function findClassroom(className) {
return new Promise(resolve => {
setTimeout(() => {
resolve('三楼303'); // 假设根据className找到的结果为:"三楼303"
}, 1000)
})
}
- 最后,找到了这名学生
3.1. 那代码怎么写呢?
- 先试试普通写法
// this
findGrade('小小').then(grade => {
findClassName(grade).then(className => {
findClassroom(className).then(classroom => {
console.log(classroom); // 三楼303
})
})
})
// or this?
findGrade('小小')
.then(grade => findClassName(grade))
.then(className => findClassroom(className))
.then(classroom => {
console.log(classroom); // 三楼303
})
第一种…有没有一种头皮发麻的感觉,第二种看起来.then是挺整齐的,但细看参数的调用还是有种头晕的感觉,这就是Promise对象的地狱回调
这还只是三层嵌套,这要是再多上几层,不说迭代人员,开发者自己都蒙了
- 来瞧瞧async/await写法
async function findStudent(name) {
const grade = await findGrade(name);
const className = await findClassName(grade);
const classroom = await findClassroom(className);
console.log(classroom); // 三楼303
}
有没有一种摄像头被擦的蹭亮蹭亮的,自拍里的自己都好看清晰很多了的感觉呢!
到这里已经很像同步代码了,很符合我们平时的代码逻辑