javascript - 如何在 node.js 可读流中调用异步函数

标签 javascript node.js asynchronous stream

这是自定义可读流实现的一个简短示例。该类称为 MyStream。流从目录中获取文件/文件夹名称并将值推送到数据事件。

为了进行比较,我(在此示例中)实现了两种不同的方式/功能。一个是同步的,另一个是异步的。构造函数的第二个参数让您决定使用哪种方式(异步为真,同步为假。

readcounter 计算_read 方法被调用的次数。只是为了提供反馈。

var Readable = require('stream').Readable;
var util = require('util');
var fs = require('fs');
util.inherits(MyStream, Readable);

function MyStream(dirpath, async, opt) {
  Readable.call(this, opt);
  this.async = async;
  this.dirpath = dirpath;
  this.counter = 0;
  this.readcounter = 0;
}

MyStream.prototype._read = function() {
  this.readcounter++;
  if (this.async === true){
    console.log("Readcounter: " + this.readcounter);
    that = this;
    fs.readdir(this.dirpath,function(err, files){
      that.counter ++;
      console.log("Counter: " + that.counter);
      for (var i = 0; i < files.length; i++){
        that.push(files[i]);
      }
      that.push(null);
    });
  } else {
    console.log("Readcounter: " + this.readcounter);
    files = fs.readdirSync(this.dirpath)
    for (var i = 0; i < files.length; i++){
      this.push(files[i]);
    };
    this.push(null);
  }
};
//Instance for a asynchronous call
mystream = new MyStream('C:\\Users', true);
mystream.on('data', function(chunk){
  console.log(chunk.toString());
});

同步方式按预期工作,但当我异步调用它时,会发生一些有趣的事情。每次通过 that.push(files[i]) 推送文件名时,都会再次调用 _read 方法。当第一个异步循环完成并且 that.push(null) 定义了流的结尾时,这会导致错误。

我用来测试的环境:node 4.1.1,Electron 0.35.2。

我不明白为什么 _read 如此频繁地被调用以及为什么会发生这种情况。也许这是一个错误?或者有什么我现在看不到的东西。 有没有办法通过使用异步函数来构建可读流?异步推送 block 真的很酷,因为这将是非阻塞流方式。特别是当您拥有大量数据时。

最佳答案

_read 在“读取器”需要数据时被调用,它通常发生在您推送数据之后。

我在直接实现 _read 时遇到了同样的“问题”,所以现在,我编写了一个返回流对象的函数。它工作得很好,数据不能从我的流中“拉出”,数据在我决定时可用/推送。以你的例子,我会这样做:

var Readable = require('stream').Readable;
var fs = require('fs');

function MyStream(dirpath, async, opt) {
  var rs = new Readable();
  // needed to avoid "Not implemented" exception
  rs._read = function() { 
    // console.log('give me data!'); // << this will print after every console.log(folder);
  };

  var counter = 0;
  var readcounter = 0;

  if (async) {
    console.log("Readcounter: " + readcounter);
    fs.readdir(dirpath, function (err, files) {
      counter++;
      console.log("Counter: " + counter);
      for (var i = 0; i < files.length; i++) {
        rs.push(files[i]);
      }
      rs.push(null);
    });
  } else {
    console.log("Readcounter: " + readcounter);
    files = fs.readdirSync(dirpath)
    for (var i = 0; i < files.length; i++) {
      rs.push(files[i]);
    };
    rs.push(null);
  }

  return rs;
}

var mystream = MyStream('C:\\Users', true);
mystream.on('data', function (chunk) {
  console.log(chunk.toString());
});

它不会直接回答您的问题,但它是获取工作代码的一种方式。

关于javascript - 如何在 node.js 可读流中调用异步函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34067221/

相关文章:

javascript - 如何在javascript中获取动态id

javascript - 在 Ionic 中使用 ng-repeat 自动滚动到底部

javascript - 在对象中查找匹配的属性名称并返回其值

ruby - 是否有适用于 Ruby 的异步日志记录库?

javascript - Typescript/Lodash group by——尝试将数组键的值与其数量分组

javascript - 在 PHP foreach 循环/数组中使用多个复选框时,在复选框单击上显示 tr id

ios - for in 循环中的完成处理程序

javascript - 使用 JavaScript 将 Canvas 图像附加到输入数组

node.js - 单击按钮触发 socket.emit

javascript - JSON.parse语法错误: Unexpected token { while parsing file with JSON