核心
其实 await 本质上等的是:后面的 thenable 对象的 then 方法调用 resolve 或者 reject。
这里面其实包含三个细节:
- thenable 对象其实就是包含 then 方法的普通对象。
- 如果 await 后面的对象不是一个 thenable 对象,那么系统会将它包装成 thenable 对象。
- Promise 对象具有 then 方法,所以 Promise 对象其实也是一个 thenable 对象。
如果理解了这三个细节,那么下面这些测试应该就很好理解了。
测试
测试一:普通 thenable 对象
const test = async () => {
try {
const data = await { then(resolve, reject) { resolve('hello') } }
console.log(data, 'data')
} catch (error) {
console.log(error, 'error')
}
}
test()
// hello data
const test = async () => {
try {
const data = await { then(resolve, reject) { reject('hello') } }
console.log(data, 'data')
} catch (error) {
console.log(error, 'error')
}
}
test()
// hello error
const test = async () => {
await { then: r => setTimeout(r, 1000) }
console.log('done')
}
test()
// 1s 之后输出 done
测试二:非 thenable 对象
const test = async () => {
const data = await 'hello'
console.log(data, 'data')
}
test()
// hello data
const test = async () => {
const data = await { a: 1 }
console.log(data, 'data')
}
test()
// { a: 1 } data
测试三:Promise 对象
const test = async () => {
try {
const data = await Promise.resolve('hello')
console.log(data, 'data')
} catch (error) {
console.log(error, 'error')
}
}
test()
// hello data
const test = async () => {
try {
const data = await Promise.reject('hello')
console.log(data, 'data')
} catch (error) {
console.log(error, 'error')
}
}
test()
// hello error
总结
总的来说,await 这个操作符,实际上会调用对象的 then 方法,并传入 resolve 和 reject 参数,等我们 then 方法中调用了 resolve 或者 reject 时 await 的结果就等到了。而对于没有 then 方法的对象或者变量,系统会自动生成一个具有 then 方法的对象(也就是Promise对象),然后将该对象或者变量作为 resolve 的参数进行调用返回。
其实我们平时一般会把 await 理解成等到后面 Promise 的返回结果,这样理解其实没有什么问题,而且覆盖我们平时编程的绝大多数场景。但是更精细一点的理解其实应该要理解到 await 本质上是在操作对象的 then 方法(调用对象的 then 方法,并传入 resolve、reject,并等待 then 方法去调用他们)。
原文链接:https://juejin.cn/post/7348762390387654696 作者:每天写一个小BUG