【问题标题】:How to run Generator Functions in Parallel?如何并行运行生成器函数?
【发布时间】:2017-08-03 18:05:59
【问题描述】:

假设我有一个带有这样端点的 Koa Web 服务器:

const perform = require(...); // some generator function

exports.endpoint = function* () {

    var results = yield getResults();

    // Respond the results
    this.body = results;
}

exports.getResults = function* () {

    var actions = [...];
    var results = [];

    for (var action of actions) {

        var result = yield perform(action);

        results.push(results);
    }

    return results;
}

现在客户端将在所有操作明显执行后得到响应。但事情是每一个动作都依赖于前一个动作的完成。

有没有办法并行执行它们?

注意:将它们转换为 Promises 不是一种选择,除非我能以某种方式返回结果,而不是 resolve() 它们。

【问题讨论】:

    标签: javascript node.js koa


    【解决方案1】:

    如果将生成器用作协程,通过模拟async/await 流程,那么您应该可以做到:

    var results = yield Promise.all(actions.map(action => perform(action)));
    

    甚至:

    var results = yield Promise.all(actions.map(perform));
    

    我不确定这里的确切用法,但是当您使用带有 coBluebird.coroutine 的生成器时,您已经在使用 Promise,因此您不妨更明确地使用它们。

    所以,而不是:

    exports.getResults = function* () {
    
        var actions = [...];
        var results = [];
    
        for (var action of actions) {
    
            var result = yield perform(action);
    
            results.push(results);
        }
    
        return results;
    }
    

    你可以试试:

    exports.getResults = function* () {
    
        var actions = [...];
    
        return yield Promise.all(actions.map(perform));
    }
    

    【讨论】:

    • 问题是perform(action)返回挂起的Generator,并不会执行实际的perform()。当产生时,Koa(或者我相信是 Bluebird.coroutine)实际上执行了这个函数。
    • 为了实际运行执行功能,我可以使用co lib,这个解决方案有意义吗? return yield Promise.all(actions.map(function(action) { return co(function*() { return yield perform(action); } }));
    • @ShaiBen-Dor 是的,这是有道理的,co 非常适合这样的事情。您还可以使用 co.wrapco 模块的一部分)和 Bluebird 的协程 - 请参阅 bluebirdjs.com/docs/api/promise.coroutine.html
    【解决方案2】:

    co 将生成器函数转换为 Promises,并异步执行它们。 Promise.all 等待他们全部完成:

    exports.getResults = function* () {
    
        var actions = [...];
    
        return yield Promise.all(actions.map(function(action) { 
            return co(function*() { 
                return yield perform(action); 
            } 
        }));
    }
    

    【讨论】:

      猜你喜欢
      • 2017-08-18
      • 2017-09-22
      • 1970-01-01
      • 2015-03-11
      • 2019-12-30
      • 2021-07-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多