彻底搞定async、await原理

async是什么

是js异步编程规范,结合await实现异步执行结果等待,将异步拥有同步代码的能力,其实底层就是一个generator生成器的语法糖。

原理

在编码的时候,会经常使用到async或者Promise,比如获取某个列表数据,两者代码如下:

// async
async function fn1() {
    let res = await getList();
    return res;
}

// promise
function fn2() {
    return new Promise((resolve,reject)=>{
        getList().then(res=>{
            resolve(res);
        });
    });
}

fn1() // 返回的是一个promise对象

从上面代码执行,可以知道async返回的是一个Promise对象,其原理通过Promise实现。await又是如何能等待其后面的代码执行呢?ES6有generator生成器的yield可以代码暂停,调用next方法执行到下一个yield。代码如下:

// 定义生成器函数
function* gen() {
    let a = yield 1;
    let b = yield 2;
    let c = yield 3;
    return a + b + c;
}
const gc = gen();
gc.next() // {value: 1, done: false}
gc.next(1) // {value: 2, done: false}
gc.next(2) // {value: 3, done: false}
gc.next(3) // {value: 6, done: true}

分析执行过程:

  1. 第一个next传参其实没有任何意义,只会执行第一个yield后面的1;

  1. 第二个next传入1,执行了 let a=和第二个yield后面的2,a=1,即next(1)参数1;

  1. 同理第三个next之后,b = 2,即next(2)参数2;

  1. 第四个next之后,c = 3,没有了yield控制,直接return,所以返回{value: 6, done: true},done为true标识已经结束。

如果后面继续next执行,得到的值是{value: undefined, done: true}

实现async

结合上面generator以及Promise的分析,可以通过generator迭代器来实现async、await原理

/**
 * 通过generator函数来实现async、await
 */
// 判断是不是promise对象
const isPromise = (o) => typeof o === 'object' && o !== null && typeof o.then === 'function';

// 转换成promise对象
const rawPromise = (val) => isPromise(val) ? val : Promise.resolve(val);

// 实现async方法
// generatorFn生成器
function asyncDeferred(generatorFn) {
    return function () {
        // 生成器对象
        const gen = generatorFn.call(this, ...arguments);
        // 返回一个Promise对象
        return new Promise((resolve, reject) => {
            // 定义一个执行next迭代的递归函数
            const runStep = function (preValue) {
                let stpVlue;
                try {
                    stpVlue = gen.next(preValue);
                } catch (err) {
                    reject(err);
                }
                const { value, done } = stpVlue;
                if (done) {
                    resolve(value);
                } else {
                    rawPromise(value).then(res => {
                        runStep(res);
                    }, err => {
                        gen.throw(err);
                        reject(err);
                    });
                }
            }
            try {
                runStep();
            } catch (err) {
                reject(err);
            }
        });
    }
}

// 定义生成器函数
function* gen() {
    let a = yield 1;
    let b = yield 2;
    let c = yield 3;
    return a + b + c;
}
// 返回一个async方法
let asyncPromise = asyncDeferred(gen);

// 执行结果
asyncPromise().then(res => {
    console.log(res); // 这里输出6
}).then(v => {
    console.log(v); // 这里输出undefined
})

注意实现:

1、所有结果必须以Promise对象返回,所以要有isPromise和rawPromise将一般返回值转换成Promise对象;
2、执行过程中还需要考虑异常错误情况,try-catch用来捕获异常。

有不妥之处,望江湖大佬指正~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值