Open lhlGitHub opened 2 years ago
async/await
其实是Promise
的语法糖,它是为优化then的嵌套调用而开发出来的。从字面上来看,async是“异步”的简写,await译为等待,所以我们很好理解async声明function是异步的,await等待是一个Promise
对象,或者是其他任何值
,并且await会暂停当前async function
的执行,等待Promise的处理完成。
async
声明的异步函数,把return后面的值通过Promise.resolve()返回Promise对象。
await
如果等待的是Promise对象,则返回Promise的处理结果;如果是其他值,则返回该值本身。若Promise正常处理(fulfillded),其将回调的resolve函数参数作为await表达式的值;若Promise处理异常(rejected),await表达式会把Promise异常原因抛出,await表达式的值为undefined,并且await表达式后面的代码被暂停了;
async/await
是一种语法糖
,用到的是ES6里的迭代函数——generator函数
generator函数
跟普通函数在写法上的区别就是,多了一个星号*
,并且只有在generator函数
中才能使用yield
,什么是yield
呢,他相当于generator函数
执行的中途暂停点
,比如下方有3个暂停点。而怎么才能暂停后继续走呢?那就得使用到next方法
,next方法
执行后会返回一个对象,对象中有value 和 done
两个属性
function* gen() {
yield 1
yield 2
yield 3
}
const g = gen()
console.log(g.next()) // { value: 1, done: false }
console.log(g.next()) // { value: 2, done: false }
console.log(g.next()) // { value: 3, done: false }
// 可以看到最后一个是undefined,这取决于你generator函数有无返回值
console.log(g.next()) // { value: undefined, done: true }
// 模拟异步操作
function fn(nums) {
return new Promise(resolve => {
setTimeout(() => {
resolve(nums * 2)
}, 1000)
})
}
// 生成器函数
function* gen() {
console.time('test')
const num1 = yield fn(1)
const num2 = yield fn(num1)
const num3 = yield fn(num2)
console.timeEnd('test')
return num3
}
function generatorToAsync(generatorFn) {
return function () {
// generatorFn有可能传参
const gen = generatorFn.apply(this.arguments)
// 模拟async函数返回一个Promise对象
return new Promise((resolve, reject) => {
// 定义一个go函数,用来自动执行 gen.next() 方法
function go(key, arg) {
let res
try {
// 相当于res = gen.next('参数')
res = gen[key](arg) // 这里有可能会执行返回reject状态的Promise
} catch (error) {
return reject(error) // 报错的话会走catch,直接reject
}
// 解构获得value和done
const { value, done } = res
if (done) {
// 如果done为true,说明走完了,进行resolve(value)
return resolve(value)
} else {
// 如果done为false,说明没走完,还得继续走
// value有可能是:常量、Promise,Promise有可能是成功或者失败
return Promise.resolve(value).then(val => go('next', val), err => go('throw', err))
}
}
go('next')// 第一次执行
})
}
}
// 测试代码
const genToAsync = generatorToAsync(gen)// 生成async函数构造器函数
const asyncRes = genToAsync()// 生成async函数
console.log(asyncRes);// async函数返回的是Promise
asyncRes.then(res=>{
// test: 3032.6279296875 ms
console.log(res);// 3秒后输出8
})
参考文章
Day4
async/await作用是用同步方式,执行异步操作 async/await实际上是用到了promise+ generator语法糖来实现的 通过yield来暂停,然后执行promise返回状态,通过内部执行.then的方式返回res给下一个next达到传参的目的,最后返回.next().value的promise状态