2021.7.12 手撕async/await源码

async/await执行机制

async和await其实是Promise和Ganerator函数的语法糖

  • 用async关键字修饰一个函数,会使这个函数内部可以使用await关键字
  • await 操作符用于等待一个Promise 对象。它只能在异步函数 async function 中使用
  • 如果await后面跟着的不是一个Promise对象,会自动将其变为Promise对象执行
  • 遇到await关键字,会立即执行跟在await后面的代码,然后将await下方的代码变成一个微任务,加入到webAPI中进行监听,等待状态改变后加入到EventQueue中等待执行

需求:ajax并行和串行

模拟数据请求

// 模拟数据请求
const query = interval => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(interval);
        }, interval);
    });
};
query(1000).then(value => {
    console.log('第一个请求成功', value);
});
query(2000).then(value => {
    console.log('第二个请求成功', value);
});
query(3000).then(value => {
    console.log('第三个请求成功', value);
});
  • 并行:同时发送多个请求,多个请求之间没有依赖「一般我们会等待所有请求都成功,整体做个啥事…」
Promise.all([query(1000), query(2000), query(3000)]).then(values => {
    console.log('三个请求都成功', values);
});
  • 串行:多个请求之间是有依赖的,第一个请求成功,才能发送第二个请求,第二个请求成功,才能发送第三个…
    • 方案一:使用Promise「解决回调地狱问题」
    query(1000).then(value => {
        console.log('第一个请求成功', value);
        return query(2000);
    }).then(value => {
        console.log('第二个请求成功', value);
        return query(3000);
    }).then(value => {
        console.log('第三个请求成功', value);
    });
    
    • 方案二:使用generator
    function* generator() {
        let value;
        value = yield query(1000);
        console.log('第一个请求成功', value);
    
        value = yield query(2000);
        console.log('第二个请求成功', value);
    
        value = yield query(3000);
        console.log('第三个请求成功', value);
    }
    let itor = generator();
    //第一次执行返回一个对象,对象的value是一个promise实例
    // itor.next().value  每一次执行next遇到yield结束,发送一个请求,value获取的是promise实例
    itor.next().value.then(value => {
        // value第一次请求的结果,第二次执行next的时候,需要把这个结果传递给next,作为第一次yeild的返回值
        itor.next(value).value.then(value => {
            // value第二次请求的结果
            itor.next(value).value.then(value => {
                // value第三次请求的结果
                itor.next(value);
            });
        });
    });
    
    • 方案三:我们把next一层层嵌套的逻辑,自动管理起来 「插件:co.js就是这样封装的」
      • generator传递的生成器函数「基于yield管理每一个要发送的请求」
      • params存储的是:后期把generator执行,传递给他的实参

模拟async/await机制实现

const AsyncFunction = function AsyncFunction(generator, ...params) {
    return new Promise((resolve, reject) => {
        let itor = generator(...params);
        const next = x => {
            let {
                value,
                done
            } = itor.next(x);
            if (done) {
                // 所有请求都成功,则返回一个状态是成功的promise实例
                resolve(value);
                return;
            }
            if (!isPromise(value)) value = Promise.resolve(value);
            value.then(result => next(result))
                .catch(reason => {
                    // 其中有一个请求失败,则返回一个状态是失败的promise实例
                    reject(reason);
                    itor.throw(reason);
                });
        };
        next();
    });
};

AsyncFunction(function* generator() {
    let value;
    value = yield query(1000);
    console.log('第一个请求成功', value);

    value = yield Promise.reject('xxx');
    console.log('第二个请求成功', value);

    value = yield query(3000);
    console.log('第三个请求成功', value);

    return 'hhh';
}).then(value => {
    console.log(`所有请求都成功`, value);
}).catch(reason => {
    console.log(`某个请求失败`, reason);
});

真实项目使用async/await处理

  • 我们上面基于 promise + generator + AsyncFunction函数,实现的就是async/await的处理机制
  • async/await是 promise + generator 的语法糖
(async function () {
    let value;
    try {
        value = await Promise.reject('xxx');
        console.log('第一个请求成功', value);
    } catch (err) {
        console.log(err);
    }

    value = await query(2000);
    console.log('第二个请求成功', value);

    value = await query(3000);
    console.log('第三个请求成功', value);
})();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值