[英]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
You can get async
to initiate the final callback by returning an error
that evaluates as true
but isn't actually an error. 通过返回评估为
true
的error
,但实际上不是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);
}
}
);
};
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.