手撕Async/await

165 阅读2分钟

工作中经常用到Async/await,但是具体实现原理并不是很懂。通过学习手撕Async/await

Async是什么

  1. async函数是使用async关键字声明的函数。 async函数是AsyncFunction构造函数的实例, 并且其中允许使用await关键字。asyncawait关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise
  2. developer.mozilla.org/zh-CN/docs/…

使用Async/await

// promise函数
function resolveFn() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve('ok')
        }, 1000)
    })
}
// async函数
async function asyncCall() {
    console.info('calling')
    const result = await resolveFn()
    console.info(result)
    return result
}
const pro = asyncCall()
// 打印'calling'
// 返回Promise对象,{PromiseState: 'fulfilled', PromiseResult: undefined}
// 1s后打印 'ok',Promise对象状态和值更新

使用Async/await

  1. Async函数返回的是Promise对象,返回结果根据执行的返回值确定
  2. await表达式必须写在Async函数中
  3. await右侧是Promise对象或其他值
  4. await失败了会抛出异常,需要try...catch获取

了解Generator/yild

Async/await是语法糖,基于Generator/yild函数封装的

function resolveFn(data) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(data * 10)
        }, 1000)
    })
}

// Generator函数
function* genFn() {
    // 中途暂停点
    yield resolveFn(1)
    yield resolveFn(2)
    return 'result'
}
// 逐步获取值
const gen = genFn()
console.info(gen.next()) // 打印 {value: Promise{<fulfilled>:10}, done: false}
console.info(gen.next()) // 打印 {value: Promise{<fulfilled>:20}, done: false}
console.info(gen.next()) // 打印 {value: 'result', done: true} // vaule为return返回值,done状态为true


// Generator函数2
function* genFn2() {
    // 中途暂停点
    const res1 = yield resolveFn(1)
    // 传入上一个yield的参数
    const res2 = yield resolveFn(res1)
    return res2
}
// then方法调用
const gen2 = genFn2()
gen2.next().value.then(res1 => {
    console.info(res1)
    gen2.next(res1).value.then(res2 => {
        console.info(res2)
        console.info(gen2.next(res2))
    })
})
// 1s打印10
// 2s打印100
// 2s打印{value: 100, done: true}

封装Async/await

// Promise函数
function resolveFn(data) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(data * 10)
        }, 1000)
    })
}
// Generator函数
function* genFn() {
  const num1 = yield resolveFn(1)
  console.info(num1) // 1s后打印10
  const num2 = yield resolveFn(num1)
  console.info(num2) // 2s后打印100
  return num2
}
// 处理函数
function AsyncFunction(fn) {
    const gen = fn()
    return new Promise((resolve, reject) => {
        function go(arg){
            let res
            // 执行Generator函数获取next结果
            try {
                res = gen.next(arg)
            } catch(err) {
                reject(err)
            }
            const {value, done} = res
            if(done) {
                resolve(value)
            } else {
                Promise.resolve(value).then(v => go(v), r => reject(r))
            }
        }
        go()
    })
}
const gen3 = AsyncFunction(genFn)
console.info(gen3) // 因为是异步调用,这里稍等2秒才能看到最终结果。Promise{PromiseState: 'fulfilled', PromiseResult: 100}

参考文章:juejin.cn/post/700703…