【问题标题】:How to end on first async parallel task completion in Node?如何结束 Node 中的第一个异步并行任务完成?
【发布时间】:2013-05-27 22:16:23
【问题描述】:

我有一个要使用https://github.com/caolan/async 并行运行的任务列表。

我希望程序在这些并行任务中的第一个完成后继续(可能通过回调),而不是全部完成。所以我觉得不幼稚

async.parallel([task1, task2], callback)

为我工作。

另外,我可以生成两个任务并取消未完成的任务,但我也不知道如何使用异步来完成。

谢谢! -查理

【问题讨论】:

  • async 任务一旦启动就无法取消;之后,它只能等待它完成或忽略它。取消的能力必须与任务或拥有它的对象一起存在。类似于XMLHttpRequest's .abort()
  • 这一事实意味着我必须尝试不同的方法 - 感谢您提供信息!

标签: javascript node.js asynchronous async.js


【解决方案1】:

平行赛

您可以通过返回一个评估为true 但实际上不是错误的error 来让async 启动最终回调。

我整理了一个使用-1 作为错误代码的示例。在最后的回调中,我检查了error 的值,如果不是-1,那么这是一个实际错误。如果错误值为-1,那么我们将在results 中有一个有效值。此时,我们只需要从 results 的其他尚未完成的异步函数中删除额外的元素。

在下面的示例中,我使用 request 模块来拉取 html 页面,并使用 underscore 模块来过滤最终回调中的结果。

var request = require('request');
var _ = require('underscore');

exports.parallel = function(req, res) {
  async.parallel([
    /* Grab Google.jp */
    function(callback) {
      request("http://google.jp", function(err, response, body) {
        if(err) { console.log(err); callback(true); return; }
        callback(-1,"google.jp");
      });
    },
    /* Grab Google.com */
    function(callback) {
      request("http://google.com", function(err, response, body) {
        if(err) { console.log(err); callback(true); return; }
        callback(-1,"google.com");
      });
    }
    ],
    /* callback handler */
    function(err, results) {
      /* Actual error */
      if(err && err!=-1) {
        console.log(err);
        return;
      }
      /* First data */
      if(err===-1) {
        /*
         * async#parallel returns a list, one element per parallel function.
         * Functions that haven't finished yet are in the list as undefined.
         * use underscore to easily filter the one result.
         */
        var one = _.filter(results, function(x) {
          return (x===undefined ? false : true);
        })[0];
        console.log(results);
        console.log(one);
        res.send(one);
      }
    }
  );
};

剩余函数结果

当您将async#parallel 设置为像这样工作时,您将无法访问其他异步函数的结果。如果您只对第一个响应的人感兴趣,那么这不是问题。但是,您将无法取消其他请求。这很可能不是问题,但可能是一个考虑因素。

【讨论】:

  • 很好的解决方案,感谢丹尼尔的代码!不幸的是,我试图运行的两项任务很大,因此让被忽略的一项完成计算成本很高。我最终可能会将任务分成更小的块,这样我就可以节省浪费的周期,要么让它完成被忽略(就像这个设计),要么只是等待两者都完成。
【解决方案2】:

async.parallel 文档说:

如果任何函数将错误传递给其回调,则立即调用主回调 与错误的值。

因此,您可以从 所有 并行仿函数返回一个错误对象,第一个完成的函数会将您跳转到完成回调。甚至可能是您自己的特殊错误类,这样您就可以区分实际错误和“嘿,我赢了”错误。

话虽如此,您仍然可以运行并行函数,可能会等待回调完成或其他任何事情。也许您可以使用async.parallelLimit 来确保您不会同时触发太多任务?

话虽如此,您可能通过尝试异步库中的另一种方法来执行此任务来获得更好的服务 - 启动并行任务然后让这些任务相互竞争可能不是最好的主意。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-07
    • 1970-01-01
    • 2021-11-28
    • 2014-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多