深入理解async/await

81 阅读1分钟

进入之前,首先我们要先知道一下为什么有asnyc/await?

在没有这两个语法糖之前,我们实现调用封装promise 通常是 xx().then().then().catch() 虽然这是避免了之前的地狱回调,但是在内部异步任务较多的情况下,不断去.then(),也会带来难以追踪,不好维护问题。

我们再看这两个语法糖的用法

async:被标记的函数 始终返回的是一个promise;

await: 使用于async内部,标记在promise前面(module顶层也可以)

代码示例
function fetchData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("Data fetched successfully!");
        }, 1000);
    });
}

async function main() {
    try { // 可以通过try-catch捕捉异常
        const data = await fetchData();
        console.log(data);
    } catch (error) {
        console.error(error);
    }
}
思考一下原理实现

async 内部返回了promise,await在**等待?**promise

引入生成器概念

语法

/* 语法 yied关键字暂停 */
function * bar(){
    console.log('step 1')
    yield 1
    console.log('step 2')
    yield 2
    console.log('step 3')
    yield 3
    // 注意 如果为return 此时状态为done,for...of 循环不会捕捉到return的值,所以需要手动处理 next()
    return 4
}

是不是跟await类似?

我们可以把这个生成器作为async内部处理的代码来模拟一下

function asyncGenerator(func) {
    return function (...args) {
        const gen = func(...args);
        function handleNext(result) { // 处理生成器iterable,这里是不是返回了一个promise?
            if (result.done) {
               return Promise.resolve(result.value);
            }
            return Promise.resolve(result.value).then(res=>{
                return handleNext(gen.next(res));
            }).catch(err=>{
                return handleNext(gen.throw(err));
            });
        }
        return handleNext(gen.next());// 简写,正常这里需要捕捉异常
    }
}
yied关键字暂停
const mockAsyncFunc = asyncGenerator(function* () {
    try {
        const result1 = yield Promise.resolve(1);
        console.log(result1);
        const result2 = yield Promise.resolve(2);
        console.log(result2);
        const result3 = yield Promise.resolve(3);
        console.log(result3);
        return 4;
    } catch (err) {
        console.log(err);
    }
});
//正常调用实现
mockAsyncFunc().then(res => { console.log(res); })

努力学习中ing,本文若有不足之处,还望大家指出~