简体   繁体   English

如何在Node中的第一个异步并行任务完成结束?

[英]How to end on first async parallel task completion in Node?

I have a list of tasks that I want to run in parallel using https://github.com/caolan/async . 我有一个我想要使用https://github.com/caolan/async并行运行的任务列表。

I want the program to proceed (probably through a callback) after the first of these parallel tasks is complete, not all of them. 我希望程序在第一个并行任务完成后继续(可能通过回调),而不是全部。 So I don't think the naive 所以我不认为天真

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

works for me. 适合我。

Alternatively I could spawn two tasks and cancel the incomplete one, but I can't figure out how to do that using async either. 或者,我可以生成两个任务并取消不完整的任务,但我也无法弄清楚如何使用异步。

Thanks! 谢谢! -Charlie -Charlie

Parallel Race 平行竞赛

You can get async to initiate the final callback by returning an error that evaluates as true but isn't actually an error. 通过返回评估为trueerror ,但实际上不是error ,可以使async启动最终的回调。

I've put together an example that uses -1 as an error code. 我整理了一个使用-1作为错误代码的示例。 In the final callback I check the error value and if it's not -1 then it's an actual error. 在最后的回调中,我检查error值,如果它不是-1那么它是一个实际的错误。 If the error value is -1 then we'll have a valid value in results . 如果错误值为-1那么我们将在results有一个有效值。 At that point, we just need to remove extra elements from results of the other async functions that have not completed yet. 此时,我们只需要从尚未完成的其他异步函数的results中删除额外的元素。

In the below example I've used the request module to pull html pages and the underscore module to filter the results in the final callback. 在下面的示例中,我使用了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);
      }
    }
  );
};

Remaining Function Results 剩余的功能结果

When you setup async#parallel to work like this you won't have access to the results of the other asynchronous functions. 当您设置async#parallel以便像这样工作时,您将无法访问其他异步函数的结果。 If you're only interested in the first one to respond then this isn't a problem. 如果您只对第一个响应感兴趣,那么这不是问题。 However, you will not be able to cancel the other requests. 但是,您将无法取消其他请求。 That's most likely not a problem, but it might be a consideration. 这很可能不是问题,但可能是一个考虑因素。

The async.parallel documentation says: async.parallel文档说:

If any of the functions pass an error to its callback, the main callback is immediately called with the value of the error. 如果任何函数将错误传递给其回调,则会立即使用错误值调用主回调。

So you could return an error object from all of your parallel functors, and the first one to finish would jump you to the completion callback. 因此,您可以从所有并行仿函数返回一个错误对象,第一个完成将跳转到完成回调。 Perhaps even your own special error class, so you can tell the difference between an actual error and a "hey I won" error. 也许甚至是你自己的特殊错误类,所以你可以区分实际错误和“嘿我赢了”错误。

Having said that, you would still have your parallel functions running, potentially waiting for callbacks to complete or whatever. 话虽如此,您仍然可以运行并行功能,可能等待回调完成等等。 Perhaps you could use async.parallelLimit to make sure you're not firing off too many tasks in parallel ? 也许您可以使用async.parallelLimit来确保您没有并行启动太多任务?

Having said all that, it's possible you are better served by trying another method from the async library for this task - firing off parallel tasks then having these tasks race each other may not be the best idea. 说完这一切之后,通过从异步库中尝试另一种方法来完成此任务可能会更好地服务 - 启动并行任务然后让这些任务相互竞争可能不是最好的主意。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM