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

发布时间 - 2026-01-11 02:45:33    点击率:

前言

前几天别人请教我关于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  # stream  # pipe  # 回调  # Node.js pipe实现源码解析  # JavaScript Reduce使用详解  # 详解JavaScript之Array.reduce源码解读  # JavaScript中reduce()的5个基本用法示例  # JS数组reduce()方法原理及使用技巧解析  # JS数组Reduce方法功能与用法实例详解  # JS数组方法reduce的用法实例分析  # JavaScript reduce和reduceRight详解  # 详解JS中的compose函数和pipe函数用法  # 是一个  # 实现了  # 是个  # 不多  # 很久  # 我们可以  # 用了  # 很简单  # 可以使用  # 写到  # 以其  # 当我们  # 教我  # 前几天  # 自带  # 转化为  # 转换成  # 于其  # 很方便 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Android GridView 滑动条设置一直显示状态(推荐)  Laravel怎么写单元测试_PHPUnit在Laravel项目中的基础测试入门  怎样使用JSON进行数据交换_它有什么限制  b2c电商网站制作流程,b2c水平综合的电商平台?  Laravel如何实现数据库事务?(DB Facade示例)  js实现获取鼠标当前的位置  Win11摄像头无法使用怎么办_Win11相机隐私权限开启教程【详解】  如何在阿里云虚拟主机上快速搭建个人网站?  PythonWeb开发入门教程_Flask快速构建Web应用  Python企业级消息系统教程_KafkaRabbitMQ高并发应用  javascript中的try catch异常捕获机制用法分析  Laravel Eloquent访问器与修改器是什么_Laravel Accessors & Mutators数据处理技巧  Win11怎么关闭资讯和兴趣_Windows11任务栏设置隐藏小组件  Android自定义控件实现温度旋转按钮效果  公司网站制作价格怎么算,公司办个官网需要多少钱?  Laravel Octane如何提升性能_使用Laravel Octane加速你的应用  Laravel Seeder怎么填充数据_Laravel数据库填充器的使用方法与技巧  如何在七牛云存储上搭建网站并设置自定义域名?  儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?  Laravel如何与Docker(Sail)协同开发?(环境搭建教程)  网站页面设计需要考虑到这些问题  网站广告牌制作方法,街上的广告牌,横幅,用PS还是其他软件做的?  如何在阿里云通过域名搭建网站?  Laravel如何为API生成Swagger或OpenAPI文档  Laravel Vite是做什么的_Laravel前端资源打包工具Vite配置与使用  百度输入法ai面板怎么关 百度输入法ai面板隐藏技巧  Laravel怎么集成Vue.js_Laravel Mix配置Vue开发环境  湖南网站制作公司,湖南上善若水科技有限公司做什么的?  如何确保西部建站助手FTP传输的安全性?  如何用景安虚拟主机手机版绑定域名建站?  如何快速重置建站主机并恢复默认配置?  ,在苏州找工作,上哪个网站比较好?  如何在阿里云部署织梦网站?  JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)  PHP怎么接收前端传的文件路径_处理文件路径参数接收方法【汇总】  米侠浏览器网页背景异常怎么办 米侠显示修复  googleplay官方入口在哪里_Google Play官方商店快速入口指南  阿里云高弹*务器配置方案|支持分布式架构与多节点部署  bing浏览器学术搜索入口_bing学术文献检索地址  Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验  简历没回改:利用AI润色让你的文字更专业  如何快速生成专业多端适配建站电话?  Python高阶函数应用_函数作为参数说明【指导】  如何在万网主机上快速搭建网站?  JavaScript如何实现类型判断_typeof和instanceof有什么区别  uc浏览器二维码扫描入口_uc浏览器扫码功能使用地址  Laravel怎么集成Log日志记录_Laravel单文件与每日日志配置及自定义通道【详解】  如何实现javascript表单验证_正则表达式有哪些实用技巧  Laravel如何保护应用免受CSRF攻击?(原理和示例)  武汉网站设计制作公司,武汉有哪些比较大的同城网站或论坛,就是里面都是武汉人的?