理解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学习笔记之Connect中间件模块(二)
Jan 27 NodeJs
nodejs 整合kindEditor实现图片上传
Feb 03 NodeJs
Nodejs从有门道无门菜鸟起飞必看教程
Jul 20 NodeJs
用nodejs的实现原理和搭建服务器(动态)
Aug 10 NodeJs
学习 NodeJS 第八天:Socket 通讯实例
Dec 21 NodeJs
NodeJS基础API搭建服务器详细过程记录
Apr 01 NodeJs
ajax +NodeJS 实现图片上传实例
Jun 06 NodeJs
NodeJS实现图片上传代码(Express)
Jun 30 NodeJs
nodejs操作mongodb的增删改查功能实例
Nov 09 NodeJs
Nodejs 发布自己的npm包并制作成命令行工具的实例讲解
May 15 NodeJs
详解从NodeJS搭建中间层再谈前后端分离
Nov 13 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
PHP实现利用MySQL保存session的方法
2014/08/23 PHP
PHP使用pcntl_fork实现多进程下载图片的方法
2014/12/16 PHP
php基于curl实现随机ip地址抓取内容的方法
2016/10/11 PHP
PHP判断表达式中括号是否匹配的简单实例
2016/10/22 PHP
Laravel5.5 数据库迁移:创建表与修改表示例
2019/10/23 PHP
JQuery Tips(3) 关于$()包装集内元素的改变
2009/12/14 Javascript
js实现按钮控制图片360度翻转特效的方法
2015/02/17 Javascript
jquery插件tytabs.jquery.min.js实现渐变TAB选项卡效果
2015/08/25 Javascript
jquery验证邮箱格式是否正确实例讲解
2015/11/16 Javascript
JS区分浏览器页面是刷新还是关闭
2016/04/17 Javascript
详解为Angular.js内置$http服务添加拦截器的方法
2016/12/20 Javascript
详解vue组件化开发-vuex状态管理库
2017/04/10 Javascript
Angular2数据绑定详解
2017/04/18 Javascript
解决vue项目使用font-awesome,build后路径的问题
2018/09/01 Javascript
微信上传视频文件提示(推荐)
2018/11/22 Javascript
antd组件Upload实现自己上传的实现示例
2018/12/18 Javascript
微信小程序indexOf的替换方法(推荐)
2020/01/14 Javascript
[02:50]2014DOTA2 TI预选赛预选赛 大神专访第一弹!
2014/05/21 DOTA
[54:10]Spirit vs NB Supermajor小组赛 A组败者组决赛 BO3 第一场 6.2
2018/06/03 DOTA
[47:03]完美世界DOTA2联赛PWL S3 access vs LBZS 第一场 12.20
2020/12/23 DOTA
[59:00]DOTA2-DPC中国联赛 正赛 Ehome vs PSG.LGD BO3 第一场 3月7日
2021/03/11 DOTA
python 动态获取当前运行的类名和函数名的方法
2014/04/15 Python
详解Python读取配置文件模块ConfigParser
2017/05/11 Python
Python3.5常见内置方法参数用法实例详解
2019/04/29 Python
深入浅析python变量加逗号,的含义
2020/02/22 Python
Python的in,is和id函数代码实例
2020/04/18 Python
分享一个python的aes加密代码
2020/12/22 Python
软件测试笔试题
2012/10/25 面试题
机关党员2014全国两会学习心得体会
2014/03/10 职场文书
2014年小学语文工作总结
2014/12/20 职场文书
支教个人总结
2015/03/04 职场文书
2016年圣诞节寄语(一句话)
2015/12/07 职场文书
最新农村养殖致富:资金投入较低的创业项目有哪些?
2019/09/26 职场文书
Spring中的使用@Async异步调用方法
2021/11/01 Java/Android
Python实现视频中添加音频工具详解
2021/12/06 Python
常用的文件对应的MIME类型汇总
2022/04/26 HTML / CSS