JavaScript协程(function*/yield)转化为异步(async/await)

JavaScript协程(function*/yield)转化为异步(async/await)

一直感觉这两者之间存在某种联系,奈何智商不够,辗转反侧了好几年,终于查到了一篇醍醐灌顶的回答 https://stackoverflow.com/questions/36196608/difference-between-async-await-and-es6-yield-with-generators

其中最关键的是打破yield用法的思维定势。一般而言yield在生成器函数里的作用相当于return,是返回数据给调用方的,调用方是主体。而现在yield需要变成类似await的关键字,需要写成诸如let a = yield 1 + 2的形式,a应该等于yield后面语句的值,也就是3。现在生成器函数是执行的主体,而调用方则是辅助的。这叫“范式转移(Paradigm Shift)”

一步步来,首先不考虑异步,如何把生成器函数转化为顺序执行的函数,比如:

let foo = transform(function* () {
    let a = yield 1 + 2;
    let b = yield 3 + 4;
    return a + b;
});

let bar = transform(function* () {
    let c = yield foo()
    return c + 5;
});

console.log(foo());
console.log(bar());

transform所做的工作就是循环执行function*next(),每一次都把上一次的返回值原封不动地再传进去,最简单的写法就是,这里省略异常处理等工作:

function transform(fn) {
    return function (...args) {
        let gen = fn(...args);
        let info = gen.next();
        while (info.done != true) {
            info = gen.next(info.value);
        }
        return info.value;
    };
}

运行,得到了期待的结果:

10
15

当然,以上最简单的写法纯属“脱裤子放屁”,没有任何实际功能,把yield都删掉结果一样,但是yield的重大意义在于让表达式的返回值“出去再进来”绕了一圈,这样就能在transform函数里进一步包装/解开Promise,正如上述StackOverflow回答里面所写的那样。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值