异步队列,文件流结束时如何知道两者完成

时间:2017-02-09 19:46:07

标签: javascript node.js callback stream async.js

将async.queue与文件流

一起使用时,我遇到了一个小问题
  1. 我有一个文件流完成的方案
  2. 我将fileRead设置为true
  3. 但队列将为空并且已经调用了排水
  4. 这导致我的“完成”永远不会被称为
  5. 在我的文件流“结束”并且队列为空之后说“结束队列”的正确方法是什么?

    var fs = require('fs')
        , util = require('util')
        , stream = require('stream')
        , es = require('event-stream');
    
    var async = require('async');
    
    var fileRead = false;
    var lineNr = 0;
    
    var q = async.queue(function(task, callback) {
        task(function(err, lineData){
            responseLines.push(lineData);
            callback();
          });
      }, 5);
    
    var q.drain = function() {
      if(fileRead){
        done(null, responseLines);
      }
    }
    
    var s = fs.createReadStream('very-large-file.csv')
        .pipe(es.split())
        .pipe(es.mapSync(function(line){
            s.pause();
            q.push(async.apply(insertIntoDb, line))
            s.resume();
        })
        .on('error', function(err){
           done(err);
        })
        .on('end', function(){
          fileRead = true;
        })
    );

    或是否有更好的使用异步,这将允许我这样做? 逐行异步处理,如果其中一行有错误,则能够提前退出

1 个答案:

答案 0 :(得分:1)

首先,我不确定你的代码段中有多少是伪代码,但var q.drain = ...不是有效的javascript而应该是错误的。它应该只是q.drain =,因为您在现有对象上定义了一个属性,而不是声明一个新变量。这可能就是为什么如果不是伪代码,你的排水功能就不会被触发。

有几种方法可以实现我认为你想要做的事情。一种方法是检查结束处理程序中队列的长度,如果仍有待处理的项目,则设置排水功能。

.on('end', function(){
  if(!q.length){
    callDone();
  }
  else {
    q.drain = callDone;
  }
});

function callDone(){
  done(null, responseLines);
}

这实际上是说"如果已经处理了队列,则调用已完成,如果没有,则调用已完成!"我确定有很多方法可以整理您的代码,但希望这可以为您的特定问题提供解决方案。