【问题标题】:What are the benefits of using yield as asynchronous control flow?使用 yield 作为异步控制流有什么好处?
【发布时间】:2019-10-21 04:29:50
【问题描述】:

Angular 的 Service worker 使用 yield 进行异步控制流。然后将每个生成器函数传递给该函数:

var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};

这和 Babel 的 _asyncToGenerator 非常相似

function _asyncToGenerator(fn) {
    return function () {
        var gen = fn.apply(this, arguments);
        return new Promise(function (resolve, reject) {
            function step(key, arg) {
                try {
                    var info = gen[key](arg);
                    var value = info.value;
                } catch (error) {
                    reject(error);
                    return;
                }
                if (info.done) {
                    resolve(value);
                } else {
                    return Promise.resolve(value).then(function (value) {
                        return step("next", value);
                    }, function (err) {
                        return step("throw", err);
                    });
                }
            }

            return step("next");
        });
    };
}

yield 用于异步控制流有什么好处?在caniuse.com 上的浏览​​器支持方面,我发现yieldawait 之间完全没有区别。

换种说法

使用这个有什么意义:

var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};

__awaiter(this, void 0, void 0, function* () {
    const foo = yield 3;
    const bar = yield new Promise(resolve => resolve(7));
    const baz = bar * foo;
    console.log(baz);
});

而不是这个:

(async function () {
    const foo = await 3;
    const bar = await new Promise(resolve => resolve('7'));
    const baz = bar * foo;
    console.log(baz);
})();

鉴于此:

【问题讨论】:

  • “将yield用于异步控制流有什么好处”-yield不用于异步控制流,它与生成器一起使用fetch the next element。您混淆了两个不同的主题。
  • 我仔细阅读了。不过,也可能是我不明白。那么请进一步解释!
  • 我知道yield 是做什么的,如果您阅读Angular 的服务工作者代码,您会注意到每个yieldfunction* 都可以替换为async/await。它是原生的,不需要像 __awaiter 这样的辅助函数
  • 同样,产量不相关。 __awaiter 函数确实使用了生成器,但它也使用了 Promise(可以用 async/await 代替)。 AFAIK 你不能用生成器替换异步/等待(不使用承诺或回调)。
  • yield 是 ES6 语法,await 是 ES7,与 ES6 相比,原生支持 ES7 的浏览器更少

标签: javascript async-await yield control-flow


【解决方案1】:

不同之处在于 Promise 旨在执行一次性任务,其中生成器旨在重复一项任务,直到任务列表用完为止。如果列表永远不会耗尽,那么生成器将继续运行,就好像它是一个可以在操作之间暂停的非基于时间 (setInterval()) 的迭代器。

这可以在生成器的 MDN 示例中看到:

function* idMaker() {
  var index = 0;
  while (true)
    yield index++;
}

var gen = idMaker(); // "Generator { }"

console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2

如果while 循环产生了一个 Promise 对象,它将类似于您提供的源示例。然后,生成器会根据需要重复生成 Promise 对象,从而为异步操作生成控制流

您在示例中提供的逻辑只是通过在需要时履行 Promise 合同来进一步推动这个场景。

【讨论】:

    猜你喜欢
    • 2015-01-27
    • 2018-01-22
    • 2017-05-28
    • 2010-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多