理解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 Stream 数据流使用手册
Apr 17 NodeJs
Nodejs高扩展性的模板引擎 functmpl简介
Feb 13 NodeJs
nodejs个人博客开发第五步 分配数据
Apr 12 NodeJs
详解nodejs微信公众号开发——6.自定义菜单
Apr 13 NodeJs
ubuntu编译nodejs所需的软件并安装
Sep 12 NodeJs
nodeJS微信分享
Dec 20 NodeJs
nodejs acl的用户权限管理详解
Mar 14 NodeJs
nodeJS服务器的创建和重新启动的实现方法
May 12 NodeJs
nodejs的路径问题的解决
Jun 30 NodeJs
NodeJs项目中关闭ESLint的方法
Aug 09 NodeJs
nodejs更新package.json中的dependencies依赖到最新版本的方法
Oct 10 NodeJs
Nodejs 数组的队列以及forEach的应用详解
Feb 25 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在文件指定行中写入代码的方法
2012/05/23 PHP
php函数重载的替代方法--伪重载详解
2015/05/08 PHP
php中strlen和mb_strlen用法实例分析
2016/11/12 PHP
PHP编程获取图片的主色调的方法【基于Imagick扩展】
2017/08/02 PHP
Laravel框架模型的创建及模型对数据操作示例
2019/05/07 PHP
如何重写Laravel异常处理类详解
2020/12/20 PHP
新浪刚打开页面出来的全屏广告代码
2007/04/02 Javascript
jquery下将选择的checkbox的id组成字符串的方法
2010/11/28 Javascript
10款新鲜出炉的 jQuery 插件(Ajax 插件,有幻灯片、图片画廊、菜单等)
2011/06/08 Javascript
JavaScript中的作用域链和闭包
2012/06/30 Javascript
jquery cookie的用法总结
2013/11/18 Javascript
JS实现弹性菜单效果代码
2015/09/07 Javascript
解决jQuery ajax请求在IE6中莫名中断的问题
2016/06/20 Javascript
jQuery.ajax实现根据不同的Content-Type做出不同的响应
2016/11/03 Javascript
JS实现动态修改table及合并单元格的方法示例
2017/02/20 Javascript
Node.js设置CORS跨域请求中多域名白名单的方法
2017/03/28 Javascript
关于HTTP传输中gzip压缩的秘密探索分析
2018/01/12 Javascript
浅谈如何使用webpack构建多页面应用
2018/05/30 Javascript
浅析 Vue 3.0 的组装式 API(一)
2020/08/31 Javascript
跟老齐学Python之大话题小函数(2)
2014/10/10 Python
Python机器学习之决策树算法
2017/12/22 Python
Python实现的三层BP神经网络算法示例
2018/02/07 Python
Django通过json格式收集主机信息
2020/05/29 Python
tensorflow dataset.shuffle、dataset.batch、dataset.repeat顺序区别详解
2020/06/03 Python
css3 box-sizing属性使用参考指南
2013/01/08 HTML / CSS
英国领先的办公用品供应商:Viking
2016/08/01 全球购物
C#笔试题和英文面试题
2013/02/07 面试题
给物业的表扬信
2014/01/21 职场文书
科技工作者先进事迹
2014/08/16 职场文书
2015年统计员个人工作总结
2015/07/23 职场文书
初中团委工作总结
2015/08/13 职场文书
小学主题班会教案
2015/08/17 职场文书
甜美蛋糕店的创业计划书模板,拿来即用!
2019/08/21 职场文书
mybatis 解决从列名到属性名的自动映射失败问题
2021/06/30 Java/Android
高性能跳频抗干扰宽带自组网电台
2022/02/18 无线电
在SQL Server中使用 Try Catch 处理异常的示例详解
2022/07/15 SQL Server