写入文件
应用场景
的应用场景主要就是处理IO操作,而http请求和文件操作都属于IO操作。这里再提一下的本质——由于一次性IO操作过大,硬件开销太多,影响软件运行效率,因此将IO分批分段进行操作,让数据像水管一样流动起来,直到流动完成,也就是操作完成。下面对几个常用的应用场景分别进行介绍
介绍一个压力测试的小工具
一个对网络请求做压力测试的工具ab,ab全称 bench,是自带的一个工具,因此使用ab必须要安装。mac os 系统自带,用户视自己的情况进行安装。运行ab之前先启动,mac os启动方式是sudo start。
bench对应参数的详细学习地址,有兴趣的可以看一下 bench对应参数的详细学习地址
介绍这个小工具的目的是对下面几个场景可以进行直观的测试,看出使用带来了哪些性能的提升。
get请求中应用
这样一个需求:
使用node.js实现一个http请求,读取data.txt文件,创建一个服务,监听8000端口,读取文件后返回给客户端,讲get请求的时候用一个常规文件读取与其做对比,请看下面的例子。
// getTest.js
const http = require('http');
const fs = require('fs');
const path = require('path');
const server = http.createServer(function (req, res) {
const method = req.method; // 获取请求方法
if (method === 'GET') { // get 请求方法判断
const fileName = path.resolve(__dirname, 'data.txt');
fs.readFile(fileName, function (err, data) {
res.end(data);
});
}
});
server.listen(8000);
// getTest2.js
// 主要展示改动的部分
const server = http.createServer(function (req, res) {
const method = req.method; // 获取请求方法
if (method === 'GET') { // get 请求
const fileName = path.resolve(__dirname, 'data.txt');
let stream = fs.createReadStream(fileName);
stream.pipe(res); // 将 res 作为 stream 的 dest
}
});
server.listen(8000);
对于下面get请求中使用的例子,会不会有些小伙伴提出质疑,难道也是一个对象,是的没错,对于那张水桶管道流转图,就是一个dest。
虽然get请求中可以使用,但是相比直接file文件读取·res.end(data)有什么好处呢?这时候我们刚才推荐的压力测试小工具就用到了。和两段代码,将data.txt内容增加大一些,使用ab工具进行测试,运行命令ab -n 100 -c 100 :8000/,其中-n 100表示先后发送100次请求,-c 100表示一次性发送的请求数目为100个。对比结果分析使用后,有非常大的性能提升,小伙伴们可以自己实际操作看一下。
post中使用
一个通过post请求微信小程序的地址生成二维码的需求。
/*
* 微信生成二维码接口
* params src 微信url / 其他图片请求链接
* params localFilePath: 本地路径
* params data: 微信请求参数
* */
const downloadFile=async (src, localFilePath, data)=> {
try{
const ws = fs.createWriteStream(localFilePath);
returnnewPromise((resolve, reject) => {
ws.on('finish', () => {
resolve(localFilePath);
});
if (data) {
request({
method: 'POST',
uri: src,
json: true,
body: data
}).pipe(ws);
} else {
request(src).pipe(ws);
}
});
}catch (e){
logger.error('wxdownloadFile error: ',e);
throw e;
}
}
看这段使用了的代码,为本地文件对应的路径创建一个对象,然后直接.pipe(ws),将post请求的数据流转到这个本地文件中,这种的应用在node后端开发过程中还是比较常用的。
post与get使用总结
和一样,都是对象,可以使用的特性,二者的区别在于,我们再看一下水桶管道流转图,
是类型,是图中的源头,而是dest类型,是图中的目的地。
在文件操作中使用
一个文件拷贝的例子
const fs = require('fs')
const path = require('path')
// 两个文件名
const fileName1 = path.resolve(__dirname, 'data.txt')
const fileName2 = path.resolve(__dirname, 'data-bak.txt')
// 读取文件的 stream 对象
const readStream = fs.createReadStream(fileName1)
// 写入文件的 stream 对象
const writeStream = fs.createWriteStream(fileName2)
// 通过 pipe执行拷贝,数据流转
readStream.pipe(writeStream)
// 数据读取完成监听,即拷贝完成
readStream.on('end', function () {
console.log('拷贝完成')
})
看了这段代码,发现是不是拷贝好像很简单,创建一个可读数据流node.js命令,一个可写数据流,然后直接通过pipe管道把数据流转过去。这种使用的拷贝相比存文件的读写实现拷贝,性能要增加很多,所以小伙伴们在遇到文件操作的需求的时候,尽量先评估一下是否需要使用实现。
前端一些打包工具的底层实现
目前一些比较火的前端打包构建工具,都是通过node.js编写的,打包和构建的过程肯定是文件频繁操作的过程,离不来,例如现在比较火的gulp,有兴趣的小伙伴可以去看一下源码。
的种类
之前的文章都是围绕前两种可读数据流和可写数据流,第四种流不太常用node.js命令,需要的小伙伴网上搜索一下,接下来对第三种数据流 说明一下。
双向的,既可读,又可写。 同时实现了和接口。 的例子包括
有什么弊端
data
.on('end', function() {
console.log('data end');
})
.pipe(a)
.on('end', function() {
console.log('a end');
})
.pipe(b)
.on('end', function() {
console.log('b end');
});
的常见类库总结
本篇文章属于进阶路线【Node必知必会系列】,看完了这篇文章是不是对有了一定的了解,并且知道了node对于文件处理还是有完美的解决方案的。本文中三次展示了水桶管道流转图,总要的事情说三遍希望小伙伴们记住它,除了以上内容小伙伴们会不会有一些思考,比如
数据流转具体内容是什么呢?二进制还是类型还是其他类型,该类型为带来了什么好处?
水桶管道流转图中的水管,也就是pipe函数什么时候触发的呢?在什么情况下触流转发?底层机制是什么?上面的疑问(由于篇幅过长拆分为两篇)会在我的第二篇文章为大家详细讲解
限时特惠:本站持续每日更新海量各大内部创业课程,一年会员仅需要98元,全站资源免费下载
点击查看详情
站长微信:Jiucxh