zoukankan      html  css  js  c++  java
  • 原生nodejs 学习笔记2

    本章节学习流, 流的一个好处在于减少各种异步IO的回调地狱。IO操作遍及我们各种操作,比如数据库读写,文件读写, 文件转换压缩……别的不说,比如第一节,我们要将一个HTML文件返回浏览器,就涉及IO操作。

    一个页面,如果按版本划分功能,可能切成一块块给不同的人做,使用fs方法的异步IO方法,可能是这样写的:

    fs.asyncXXX(function(err,data){
       fs.asyncXXX(function(err,data){
          fs.asyncXXX(function(err,data){
             fs.asyncXXX(function(err,data){
    
             })
          })
       })
    })
    

    如果使用流,则是这样写

    readStream.pipe(transformStream).pipe(writeStream)
    
    a.pipe(b).pipe(c).pipe(d)
    //相当于
    a.pipe(b);
    b.pipe(c);
    c.pipe(d);
    
    

    这是不是与Unix中的管道很相似呢?!无错,它的灵感就在于这!

    
    a | b | c | d
    

    此外,不使用流,如果读出一个很大的文件,则需要将它整个装进内存中,这会很影响性能。使用了流就不用担心这个。

    nodejs底层一个提供了4个流, Readable 流、Writable 流、Duplex 流和Transform 流。如果还不能满足你的需求,可以自己继承其个流的基类进行扩展。(例如util.inherits(MyTransform, Transform); )

    使用情景需要重写的方法
    只读Readable_read
    只写Writable_write
    双工Duplex_read, _write
    操作被写入数据,然后读出结果Transform_transform, _flush

    说了这么多,我们还没有瞧见一个流。我们来一些例子吧.

    可读流:

    //aaa.js
    var fs = require('fs');
    var readStream = fs.createReadStream('myfile.txt');//里面乱写几行
    readStream.pipe(process.stdout);
    

    上面是直接读文本的,然后输出到控制台。我们也可以加密一下输出

    
    var crypto = require('crypto');
    var fs = require('fs');
    
    var readStream = fs.createReadStream('myfile.txt');
    var hash = crypto.createHash('sha1');
    readStream
      .on('data', function (chunk) {
        hash.update(chunk);
      })
      .on('end', function () {
        console.log(hash.digest('hex'));
      });
    

    输出一大堆看不懂的密码:

    fs模块也有创建可读流的方法:

    
    var fs = require('fs');
    var readableStream = fs.createReadStream('file.txt');
    var data = '';
    
    readableStream.setEncoding('utf8');
    
    readableStream.on('data', function(chunk) {
        data+=chunk;
    });
    
    readableStream.on('end', function() {
        console.log(data);
    });
    
    

    我们再看一下可读流的各种事件

    var fs = require('fs');
    
    var readStream = fs.createReadStream('myfile.txt');
    readStream
      .on('data', function (chunk) {
      	console.log("emit data")
        console.log(chunk.toString('utf8'))
      })
      .on('end', function () {
        console.log("emit end");
      })
      .on('close', function () {
        console.log("emit close");
      })
      .on("readable", function(){
         console.log("emit readable")
      })
      .on("error", function(e){
         console.log("emit error")
      })
    
    

    再看一下如何重写_read方法:

    var Readable = require('stream').Readable;
    var util = require('util');
    
    function CountingObjectStream(length, options) {
      if (!(this instanceof CountingObjectStream)) {
        return new CountingObjectStream(length, options);
      }
      if (!options) options = {}; // ensure object
      options.objectMode = true; // forcing object mode
      Readable.call(this, options);
      this.lenToCount = length;  // how far to count
      this.index = 0;  // to track our count
    }
    util.inherits(CountingObjectStream, Readable);
    
    CountingObjectStream.prototype._read = function () {
      this.index += 1;
      if (this.index > this.lenToCount) {
        return this.push(null); // done, return
      }
    
      // pushing number, but could be any non-null obj
      this.push(this.index);
    };
    
    
    // consume this stream and output to stdout
    // coercing it to a string
    var readStream = new CountingObjectStream(10);
    readStream
      .on('readable', function () {
        var obj;
        while (null !== (obj = readStream.read())) {
          console.log(obj);
        }
      });
    

    Readable有一个可选的hash参数里,里面有三个配置项:

    • highWaterMark {Number} 停止从底层资源读取前内部缓冲区最多能存放的字节数。缺省为 16kb,对于 objectMode 流则是 16
    • encoding {String} 若给出,则 Buffer 会被解码成所给编码的字符串。缺省为 null
    • objectMode {Boolean} 该流是否应该表现为对象的流。意思是说 stream.read(n) 返回一个单独的对象,而不是大小为 n 的 Buffer

    前两个配置项比较易懂,我们看第三个:

    
    var stream = require('stream');
    var util = require('util');
    
    function StringifyStream(){
        stream.Transform.call(this);
    
        this._readableState.objectMode = false;
        this._writableState.objectMode = true;
    }
    util.inherits(StringifyStream, stream.Transform);
    
    StringifyStream.prototype._transform = function(obj, encoding, cb){
        this.push(JSON.stringify(obj));
        cb();
    };
    
    
    var json = require(__dirname + 'test.json');
    console.log(json) //这是一个对象
    var rs = new stream.Readable({ objectMode: true });
    rs.push(json);
    rs.push(null);
    
    rs.pipe(new StringifyStream()).pipe(process.stdout);
    
    

    下面是test.json

    
    {
    "a":"2",
    "b":{
          "xxx": 1,
    	   "yyy": false
       }
    }
    

    可写流

    构造器有一个可选配置对象,默认是编码是utf8

    
    var fs = require('fs');
    var wstream = fs.createWriteStream('myOutput.txt');
    wstream.write('Hello world!
    ');
    wstream.write('Another line
    ');
    wstream.end();
    
    

    我们可以这样改编码

    
    var fs = require('fs');
    var wstream = fs.createWriteStream('myOutput.txt');
    wstream.write('Hello world!
    ');
    wstream.write('Another line
    ');
    wstream.end();
    
    

    输出二进制文件

    var crypto = require('crypto');
    var fs = require('fs');
    var wstream = fs.createWriteStream('myBinaryFile');
    // creates random Buffer of 100 bytes
    var buffer = crypto.randomBytes(100);
    wstream.write(buffer);
    // create another Buffer of 100 bytes and write
    wstream.write(crypto.randomBytes(100));
    wstream.end();
    
    
    http://www.sandersdenardi.com/readable-writable-transform-streams-node/ http://www.slideshare.net/shigeki_ohtsu/stream2-kihon https://cnodejs.org/topic/513ef6cc069911196d0c90a6 http://nodeapi.ucdok.com/#/api/stream.html http://www.it165.net/pro/html/201406/15924.html http://calv.info/an-introduction-to-nodes-new-streams/ http://codewinds.com/blog/2013-08-20-nodejs-transform-streams.html http://stackoverflow.com/questions/20317759/implementing-a-buffered-transform-stream http://maxogden.com/node-streams.html http://codewinds.com/blog/2013-08-19-nodejs-writable-streams.html、 http://codewinds.com/blog/2013-08-04-nodejs-readable-streams.html http://codewinds.com/blog/2013-08-20-nodejs-transform-streams.html
  • 相关阅读:
    在eclipse中快速多行注释的方法
    Android开发:去掉Activity的头部标题栏及全屏显示
    C#的Process类的一些用法
    C#中隐式操作CMD命令行窗口 (转)
    我的INI 配置文件读写动态库
    Android高手进阶教程(五)之----Android 中LayoutInflater的使用!
    Android高手进阶教程(六)之----Android 中MenuInflater的使用(布局定义菜单)!
    Android Menu 之 optionsMenu 详解
    centos安装php扩展
    linux 权限
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/4345478.html
Copyright © 2011-2022 走看看