在node.js中返回一组N个asynchronous调用的第一个/最快M个结果的最有效方法是什么?

我正在将一个缓慢的asynchronous谓词函数(它调用一个外部HTTP API)应用到N个input的列表中。 我只需要任何M(其中M <= N)的input,函数返回true。 我的第一个尝试是:

var async = require('async'); function asyncFilterFirstM(inputs, m, fn, finalCb) { var outs = []; var alreadyReturned = false; async.map(inputs, function(input, cb) { fn(input, function(ret) { if (ret) { outs.push(input); if (outs.length === m) { alreadyReturned = true; finalCb(null, outs); } } cb(null, ret); }); }, function(err) { if (!alreadyReturned) { if (err) return finalCb(err); finalCb(null, outs); } }); } 

这个版本的问题是:

  1. 其余的M – N电话不会被取消。
  2. finalCb不一定立即被调用。 它往往会阻止其他正在进行的慢速呼叫,破坏了预期优化的目的。

如果你希望你的函数在所有操作完成之前返回,那么我认为你不能使用async#map。 此外,asynchronous不会提供任何API来取消正在运行的任务。

这是我该怎么做的。 每个迭代器都可以返回一个中止函数。 它可以像下面这样简单:

 function (input, done) { var req = http.createClient(); … return function () { req.abort(); } } 

如果你正在做一个HTTP请求。

 function asyncMapFastest(arr, m, iterator, done) { var remaining = m, results = {}, aborts = [], finished = false; function abortStillRunning() { finished = true; aborts.forEach(function (abort) { if (abort) abort(); }); aborts = []; } arr.forEach(function (input, i) { var abort = iterator(input, function (err, result) { if (finished) return; if (err) { abortStillRunning(); return done(err); } remaining--; results[input] = result; aborts[i] = null; if (remaining === 0) { abortStillRunning(); return done(null, results); } }); aborts[i] = abort; }); }