Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在node.js中迭代大量异步调用/结果(使用ES6/async/bluebird/generators)?_Javascript_Node.js_Promise_Bluebird_Node Async - Fatal编程技术网

Javascript 在node.js中迭代大量异步调用/结果(使用ES6/async/bluebird/generators)?

Javascript 在node.js中迭代大量异步调用/结果(使用ES6/async/bluebird/generators)?,javascript,node.js,promise,bluebird,node-async,Javascript,Node.js,Promise,Bluebird,Node Async,我正在node.js中编写一个实用程序,它必须每天晚上处理和连接大量文件。在同步伪代码中,为了清晰起见,省略try/catch看起来是这样的: while (true) { var next = db.popNext(); if (!next) return; out.append(next); } 然而,在我使用的库中,popNext实际上是一个节点样式的异步方法,看起来像这样:popNextcallback 因为我从头开始编写中间件,所以我可以使用-harmony

我正在node.js中编写一个实用程序,它必须每天晚上处理和连接大量文件。在同步伪代码中,为了清晰起见,省略try/catch看起来是这样的:

while (true) {
    var next = db.popNext();
    if (!next) return;

    out.append(next);
}
然而,在我使用的库中,popNext实际上是一个节点样式的异步方法,看起来像这样:popNextcallback

因为我从头开始编写中间件,所以我可以使用-harmony,例如,或

理想情况下,我更喜欢:

forEachOrdered(db.popNext, (error, next, ok, fail) => {
   if(error) return; // skip

   // If there was an internal error, terminate the whole loop.
   if(out.append(next)) ok();
   else fail();
}).then(() => {
   // All went fine.
}).catch(e => {
   // Fail was called.
});
然而,我对其他“标准”解决方案持开放态度。我想知道这个问题最简洁的解决方案是什么


编辑只是在一个常规for循环中同时生成所有内容可能无法解决我的问题,因为我们讨论的是100k,对于我必须打开并读取的每个项目,我可能会用完文件描述符

下面是一个使用bluebird协同程序并使用理想代码的解决方案:

var db = Promise.promisifyAll(db);

var processAll = Promise.coroutine(function*(){
  while(true){
    var next = yield db.popNextAsync(); // promisify gives Async suffix
    if(!next) return;
    out.append(next); // some processing
  }       
});
在ES2016 ES7中,这成为:

var db = Promise.promisifyAll(db); // still need to promisify

async function processAll(){
  let next;
  while(next = await db.popNextAsync()){
     // whatever
     out.append(next);
  }
}
尽管如此,我认为输出集合也应该是一个iterable和lazy,因此使用ES2016异步迭代器:

var db = Promise.promisifyAll(db);
async function* process(){
    while(true){
       var val = await db.popNextAsync();
       if(!val) return;
       // process val;
       yield process(val); // yield it forward
    }
}
虽然如果我们真的想在这里全力以赴,但在将db.popNext转换为异步迭代器后,这在ES2016 async for notation中变成了:

async function* processAll(){
    for async(let next of db.asAsyncIterator()){ // need to write this like above
       yield process(next); // do some processing
    }
}
利用整个ES2016异步迭代API。如果不能或不想使用生成器,则始终可以将while循环转换为递归:

function processAll(){ // works on netscape 7
   return db.popNextAsync().then(function next(value){
      if(!value) return;
      out.push(process(value));
      return db.popNextAsync().then(next); // after bluebird promisify
   });
}

你在使用Babeljs吗?不,但是我可以考虑。如果你说是理想的话,有没有更好的,即更实际的方法来做?@ Lefft4Boice第一个版本的代码在没有任何转发器的情况下工作,或者在今天的节点上有任何怪癖。所有其他版本都需要traspilation babel,这是最后一个版本——目前还没有人编写过transpiler,但它是标准化的。大约一个月前,在最后一个之前的一个被添加到再生器中。嗯,我尝试了解决方案1,它似乎在原则上起作用。但是,我注意到当yield db.popNextAsync出现错误时,整个循环将终止,即调用processAll.catch。有没有办法像我上面更新的问题中那样优雅地拦截db.popNextAsync承诺?@left4bread用try/catch围绕它们是一个好的开始:@left4bread好吧,这里有两个问题。我知道这一点,是因为我自己实现过几次协同程序,我是一名积极的bluebird贡献者,编写过这样的代码,并且有使用其他语言类似技术的经验。至于实际的问题-承诺和生成器都是关于回收sane同步控制流的,您可以尝试/捕获,可以抛出/返回,并执行类似于同步JS的操作。顺便说一句,对于新的3.0文档,我们非常欢迎拉取请求