如何在 nodejs 中进行大量但未知数量的 REST http 调用?

How do I make a large but unknown number of REST http calls in nodejs?

我有一个orientdb数据库。我想使用带有 RESTfull 调用的 nodejs 来创建大量记录。我需要获取每个的 @rid 以便稍后处理。

我的伪代码是:

for each record
  write.to.db(record) 
  when the async of write.to.db() finishes
     process based on @rid
carryon()

我因此陷入了严重的回调地狱。最接近的版本在 .then 函数中使用尾递归将下一条记录写入数据库。但是,我无法继续进行其余的处理。

最后一个限制是我在公司代理后面,不通过网络管理员就不能使用任何其他包,所以使用本机 nodejs 包是必不可少的。

有什么建议吗?

对于完成回调,此类问题的一般设计模式使用本地函数来执行每次写入:

var records = ....;    // array of records to write
var index = 0;

function writeNext(r) {
    write.to.db(r, function(err) {
       if (err) {
          // error handling
       } else {
          ++index;
          if (index < records.length) {
             writeOne(records[index]);
          }
       }
    });
}

writeNext(records[0]);

这里的关键是你不能使用像.forEach()这样的同步迭代器,因为它们不会一次迭代一个并等待完成。相反,您进行自己的迭代。


如果您的写入函数 returns 是一个 promise,您可以使用 .reduce() 迭代数组常用的模式。

var records = ...;    // some array of records to write

records.reduce(function(p, r) {
    return p.then(function() {
       return write.to.db(r);
    });
}, Promsise.resolve()).then(function() {
   // all done here
}, function(err) {
   // error here
});

此解决方案将承诺链接在一起,在执行下一个保存之前等待每个承诺解决。

很难判断哪个函数最适合您的场景 w/o 更多细节,但我几乎总是使用 asyncjs 来处理这种事情。

根据您的说法,一种方法是 async.map:

var recordsToCreate = [...];

function functionThatCallsTheApi(record, cb){
   // do the api call, then call cb(null, rid)
}

async.map(recordsToCreate, functionThatCallsTheApi, function(err, results){
   // here, err will be if anything failed in any function
   // results will be an array of the rids
});

您也可以查看其他的启用节流,这可能是个好主意。