node.js——Stream

Stream 流

stream 是一个抽象接口,node 中有很对象实现了这个接口。例如,对http 服务器发起请求的request 对象就是 一个stream,还有stdout(标准输出)。Stream 可以是只读、可写,也可以同时可读可写。所有的Stream 对象 都是EventEmitter 的实例。
这里写图片描述

Readable Stream 可读流

可读流:用来提供数据,外部来源的数据可被存储到内部的Buffer里面缓存起来。
一个可读流有如下方法、成员、和事件。

1.Event: ‘data’

‘data’事件的参数是Buffer(默认情况下),如果调用过setEncoding()方法,则参数为一个字符串。

2.Event: ‘end’

此事件在流遇到EOF(在TCP 中为FIN)时被触发,表示该流不会再有数据(不会再次触发’data’事件)。如果该流 也是可写流,则它还可以继续写入。

3.Event: ‘error’

在收取数据出错时被触发。

4.Event: ‘close’

内部的文件描述符被关闭时被触发,并不是所有的流都会触发此事件。(例如,一个进入的(incoming)HTTP 请 求将不会触发’close’事件)。

5.Event: ‘fd’

当数据流接收到文件描述符信息时触发该事件(一个文件数据流包含两部分信息:文件描述符信息和文件的数 据信息)。本事件只支持Unix 数据流,其他类型的流不会触发该事件。

6.stream.readable

一个布尔值,默认为true。当遇到错误或流读到结尾或者调用destory()函数后,该值被设置为false。

7.stream.setEncoding(encoding)

该函数设置data 事件返回字符串而不是Buffer 对象。编码类型可以设置为”utf8”,”ascii”或”base64”。

8.stream.pause()

暂停触发data 事件。

9.stream.resume()

恢复触发’data’事件。

10.stream.destroy()

关闭内部的文件描述符。这样该流将不会再触发任何事件。

示例代码如下:

var fs = require('fs');

var readStream = fs.createReadStream('stream_Copy_Logo.js');
var n = 0;
    readStream
    .on('data', function(chunk){
        console.log("data emit");
        n++;
        console.log(Buffer.isBuffer(chunk));
        // console.log("stream" + chunk.toString());
        readStream.pause();
        console.log("Data Pause!");
        setTimeout(function(){
            readStream.resume();
        console.log("Data resume!");    
        },3000);
    })
    .on('readable', function(){
        console.log('readable');
    })
    .on('end', function(){
        console.log("n"+n);
        console.log("end");
    })
    .on('close', function(){
        console.log('close');
        readStream.close();
    })

11.Event: ‘pipe’
‘pipe’事件时发出stream.pipe()方法读取流,添加这个可写至目的地。
pipe()方法会自动监听data和end事件,源端数据会源源不断地发送至pipe链末端,除此以外,pipe方法还可以自动控制后端压力;在目的地写入数据缓慢时,node可以将尽可能少的缓存放置于内存中;通过对内存空间的调度就能实现自动控制流量;并且数据在pipe时,只要pipe链末端真正需要数据时数据才会从源头被取出

const writer = getWritableStreamSomehow();
const reader = getReadableStreamSomehow();
writer.on('pipe', (src) => {
  console.error('something is piping into the writer');
  assert.equal(src, reader);
});
reader.pipe(writer);

边下载边pipe

var http = require("http");
var fs = require("fs");
var request = require('request');
http
    .createServer(function(req, res){
        // fs.readFile('../Buffer/log.png', function(err,data){
        //  if(err)
        //  {
        //      res.end('file is not exist!');
        //  }else{
        //      res.writeHeader(200, {'Context-Type': 'text/html'});
        //      res.end();
        //  }
        // var readStream = fs.createReadStream("../Buffer/log.png").pipe(res);
        //线上图片
        request('http://static.mukewang.com/static/img/common/logo.png').pipe(res);
        }).listen(8090);
});

Writable Stream 可写流

可写流:用来消费数据,从可读流里获取数据以后,然后对得到Bufer数据进行处理。
一个可写流具备以下方法、成员、和事件。

1.Event: ‘drain’

在一个wrire() 方法被调用并返回false 后触发,表明可以安全的再次写入该stream。

2.Event: ‘error’

在异常发生赤错误时被触发。

3.Event: ‘close’

当底层的文件描述符已终止时发出。

4.stream.writeable

一个boolean 值,缺省为true ,但是在一个’error’产生或是end() / destroy() 被调用后,会变为false 。

5.stream.write(string, encoding=’utf8’, [fd])

使用指定的编码将字符串字符串写入到流中。如果字符串已被刷新到内核缓冲区,返回true。返回false 则表明 内核缓冲区已满,数据将在未来被发送出去。’drain’事件用来通知内核缓冲区何时为空。此方法的默认编码为 ‘utf8’。

如果指定了可选参数fd,它将被当做一个文件描述符并通过流来发送。它只支持UNIX 流,否则会被忽略且没 有任何提示。当用这种方式发送文件描述符时,在流清空之前关闭文件描述符可能导致发送出非法的描述符。

6.stream.write(buffer)

同上,除了使用一个原始缓冲区。

7.stream.end()

通过EOF 或FIN 来终止流。

8.stream.end(string, encoding)

根据指定的编码发送字符串,并通过EOF 或FIN 来终止流。这对于减少发送数据包的数量是非常有用的。

9.stream.end(buffer)

同上,但使用一个缓冲区。

10.stream.destroy()
终止底层的文件描述符,此后流不再发出任何事件。

示例代码:

var fs = require('fs');

// var source = fs.readFileSync('../Buffer/log.png');
// fs.writeFileSync('stream_Copy_Logo.png', source);
var readStream = fs.createReadStream('../Buffer/log.png');
var writeStream = fs.createWriteStream('stream_Copy_Logo2.png');

readStream
.on('data', function(chunk){
    if(writeStream.write(chunk) == false)  //数据还在缓存中,未写入至目标
    {
        console.log("still cached!")
        readStream.pause();
    }
})
.on('end', function(){
    writeStream.end();
})
writeStream.on("drain", function(){
    console.log("data drains");

    readStream.resume();
})

Duplex Stream 双工流

双工流:实现了readable与writeable两个接口;

Transform Stream 转换流

转换流:也是双工的,可读可写,但是不保存数据,只负责处理流经其的Buffer对象。

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

var readStream = new Readable();
var writeStream = new Writable();

readStream.push("I ");
readStream.push("Love ");
readStream.push("Moc ");
readStream.push(null);

writeStream._write = function(chunk, encode, cb){
    console.log(chunk.toString());
    cb();
}

readStream.pipe(writeStream);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值