理解nodejs的stream和pipe机制的原理和实现


Posted in NodeJs onAugust 12, 2017

前言

前几天别人请教我关于pipe的问题,我发现我虽然用了nodejs很久,但是由于每次用的不多所以经常回避stream的使用,导致一直不熟,现在重新学习整理一下相关知识。

通过nodeschool学习stream

nodeschool有一个stream-adventure教程教导stream的使用,很简单

简单stream进行pipe

首先,我们可以通过管道将输入定位到输出,输入输出可以是控制台或者文件流或者http请求,比如

process.stdin.pipe(process.stdout)
process.stdin.pipe(fs.createWriteStream(path))
fs.createReadStream(path).pipe(process.stdin)

pipe中间进行处理

如果我们想要在管道中间进行处理,比如想将输入的字符串变成大写写到输出里,我们可以使用一些可以作为中间处理的框架,比如through2就很方便

var through2 = require('through2');
var stream = through2(write,end)
process.stdin
  .pipe(stream)
  .pipe(process.stdout);

function write(line,_,next){
  this.push(line.toString().toUpperCase())
  next();
})
function end(done){
  done();
})

stream转化成普通回调

当我们输入是流,而输出是个普通函数,我们需要把输入流转化为普通的buffer,这时可以试用concat-stream库

var concat = require('concat-stream');

var reverseStream=concat(function(text){
  console.log(text.toString().split("").reverse().join(""));
})

process.stdin.pipe(reverseStream)

http server中的流

类似stdin和fs,http由于其特性也适合使用流,所以其自带类似特性

var http = require('http');
var server = http.createServer(function(req,res){
  req.pipe(res);
})

既作为输入也作为输出的流

request框架实现了如下功能,将一个流pipe到request请求中,然后将流的内容发给服务器,然后返回作为流供其他代码使用,实现如下

var request = require('request');
var r = request.post('http://localhost:8099');
process.stdin.pipe(r).pipe(process.stdout)

分支管道

下边是一个例子,这个例子将输入管道中html包含loud class的元素放入另一个管道进行大写操作,然后最后合并成输出

var trumpet = require('trumpet');
var through2 = require('through2');
var fs = require('fs');
var tr = trumpet();
var stream = tr.select('.loud').createStream();
var upper = through2(function(buf,_,next){
  this.push(buf.toString().toUpperCase());
  next();
})
stream.pipe(upper).pipe(stream);
process.stdin.pipe(tr).pipe(process.stdout);

合并输入输出stream例子

合并后的输入输出可像前文request一样使用,下边这个例子实现了使用流的方式进行子进程调用

var spawn = require('child_process').spawn;
var duplexer2 = require('duplexer2');

module.exports = function(cmd, args){
  var c = spawn(cmd,args)
  return duplexer2(c.stdin,c.stdout)
}

总结

通过上边的例子,可以知道stream应该还有如何合并等更复杂的应用方式。总之整体上符合如下特性:

  • Stream分为readable、writeble
  • Stream通过pipe方法控制流向
  • httpServer和httpClient和file system和process.stdin\out\err通常可以作为stream
  • Stream可以被on(event)转化为普通的变量,普通变量可以被write转换成stream
  • Stream自身可以被拆分、合并、过滤

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

NodeJs 相关文章推荐
nodejs npm install全局安装和本地安装的区别
Jun 05 NodeJs
Nodejs学习笔记之NET模块
Jan 13 NodeJs
NodeJS学习笔记之(Url,QueryString,Path)模块
Jan 13 NodeJs
nodejs导出excel的方法
Jun 30 NodeJs
使用DNode实现php和nodejs之间通信的简单实例
Jul 06 NodeJs
利用nodejs监控文件变化并使用sftp上传到服务器
Feb 18 NodeJs
用nodeJS搭建本地文件服务器的几种方法小结
Mar 16 NodeJs
NodeJS测试框架mocha入门教程
Mar 28 NodeJs
nodejs动态创建二维码的方法
Aug 12 NodeJs
利用nodeJs anywhere搭建本地服务器环境的方法
May 12 NodeJs
基于Nodejs的Tcp封包和解包的理解
Sep 19 NodeJs
用Nodejs实现在终端中炒股的实现
Oct 18 NodeJs
Windows下快速搭建NodeJS本地服务器的步骤
Aug 09 #NodeJs
让nodeJS支持ES6的词法----babel的安装和使用方法
Jul 31 #NodeJs
浅谈nodejs中的类定义和继承的套路
Jul 26 #NodeJs
nodejs之get/post请求的几种方式小结
Jul 26 #NodeJs
nodejs前端自动化构建环境的搭建
Jul 26 #NodeJs
nodejs body-parser 解析post数据实例
Jul 26 #NodeJs
深入解析nodejs HTTP服务
Jul 25 #NodeJs
You might like
10条PHP编程习惯助你找工作
2008/09/29 PHP
深入PHP运行环境配置的详解
2013/06/04 PHP
PHP移动文件指针ftell()、fseek()、rewind()函数总结
2014/11/18 PHP
Yii实现MySQL多数据库和读写分离实例分析
2014/12/03 PHP
ZendFramework框架实现连接两个或多个数据库的方法
2016/12/08 PHP
发一个自己用JS写的实用看图工具实现代码
2008/07/26 Javascript
jQuery 技巧小结
2010/04/02 Javascript
js鼠标左右键 键盘值小结
2010/06/11 Javascript
Javascript计算时间差的函数分享
2011/07/04 Javascript
解决jQuery动态获取手机屏幕高和宽的问题
2014/05/07 Javascript
jquery插件star-rating.js实现星级评分特效
2015/04/15 Javascript
动态加载JavaScript文件的两种方法
2016/04/22 Javascript
Jquery基础之事件操作详解
2016/06/14 Javascript
RequireJS简易绘图程序开发
2016/10/28 Javascript
详解nodejs的express如何自动生成项目框架
2017/07/12 NodeJs
理解 Node.js 事件驱动机制的原理
2017/08/16 Javascript
Node.js学习之查询字符串解析querystring详解
2017/09/28 Javascript
关于axios如何全局注册浅析
2018/01/14 Javascript
jquery将json转为数据字典的实例代码
2019/10/11 jQuery
基于js判断浏览器是否支持webGL
2020/04/18 Javascript
vue键盘事件点击事件加native操作
2020/07/27 Javascript
[58:15]2018DOTA2亚洲邀请赛 4.1 小组赛 A组 NB vs Liquid
2018/04/02 DOTA
[49:12]完美世界DOTA2联赛PWL S2 Magma vs GXR 第二场 11.29
2020/12/02 DOTA
解决python爬虫中有中文的url问题
2018/05/11 Python
基于tensorflow加载部分层的方法
2018/07/26 Python
PyQt5多线程刷新界面防假死示例
2019/12/13 Python
pyenv虚拟环境管理python多版本和软件库的方法
2019/12/26 Python
Python 基于FIR实现Hilbert滤波器求信号包络详解
2020/02/26 Python
Python基于BeautifulSoup爬取京东商品信息
2020/06/01 Python
Python+kivy BoxLayout布局示例代码详解
2020/12/28 Python
详解解决jupyter不能使用pytorch的问题
2021/02/18 Python
纯css3实现思维导图样式示例
2018/11/01 HTML / CSS
微软巴西官方网站:Microsoft Brasil
2019/09/26 全球购物
幼儿运动会邀请函
2014/01/17 职场文书
三方协议书
2015/01/27 职场文书
2015年教师见习期工作总结
2015/05/20 职场文书