首页 >

用NODE.JS中的流编写工具是要注意的事项【node.js】

web前端|js教程用NODE.JS中的流编写工具是要注意的事项【node.js】
NODE.JS,流
web前端-js教程
Node.js中的流十分强大,它对处理潜在的大文件提供了支持,也抽象了一些场景下的数据处理和传递。正因为它如此好用,所以在实战中我们常常基于它来编写一些工具 函数/库 ,但往往又由于自己对流的某些特性的疏忽,导致写出的 函数/库 在一些情况会达不到想要的效果,或者埋下一些隐藏的地雷。本文将会提供两个在编写基于流的工具时,私以为有些用的两个tips。
网站推广赚钱源码,UBUNTU下载视频制作,一个tomcat两个端口号,python爬虫登录qq,iis和php关联结合的模块,西城seo教程lzw
一,警惕EVENTEMITTER内存泄露
淘宝客源码程序,vscode vi 配置,天猫魔盒ubuntu,tomcat pdf 中文,怎么打开sqlite视频,discuzx3.2插件附件,微信前端框架ui,厦门爬虫户外俱乐部,win 配置php,meta标签 seo,信息发布微网站模板,网页动态客服代码,免费商业模板,html5 手机页面 加载,集装箱运输管理系统源码,jsp 登录程序lzw
在一个可能被多次调用的函数中,如果需要给流添加事件监听器来执行某些操作。那么则需要警惕添加监听器而导致的内存泄露:
公司转让网站源码,ubuntu截取ip,tomcat发布后没有工程,网络爬虫演讲,php面试选择题及答案,平湖seo推广一体化lzw
'use strict';const fs = require('fs');const co = require('co');function getSomeDataFromStream (stream) { let data = stream.read(); if (data) return Promise.resolve(data); if (!stream.readable) return Promise.resolve(null); return new Promise((resolve, reject) => {  stream.once('readable', () => resolve(stream.read()));  stream.on('error', reject);  stream.on('end', resolve); })}let stream = fs.createReadStream('/Path/to/a/big/file');co(function *() { let chunk; while ((chunk = yield getSomeDataFromStream(stream)) !== null) {  console.log(chunk); }}).catch(console.error);
在上述代码中,getSomeDataFromStream函数会在通过监听error事件和end事件,来在流报错或没有数据时,完成这个Promise。然而在执行代码时,我们很快就会在控制台中看到报警信息:(node) warning: possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit.,因为我们在每次调用该函数时,都为传入的流添加了一个额外的error事件监听器和end事件监听器。为了避免这种潜在的内存泄露,我们要确保每次函数执行完毕后,清除所有此次调用添加的额外监听器,保持函数无污染:

function getSomeDataFromStream (stream) { let data = stream.read(); if (data) return Promise.resolve(data); if (!stream.readable) return Promise.resolve(null); return new Promise((resolve, reject) => {  stream.once('readable', onData);  stream.on('error', onError);  stream.on('end', done);  function onData () {   done();   resolve(stream.read());  }  function onError (err) {   done();   reject(err);  }  function done () {   stream.removeListener('readable', onData);   stream.removeListener('error', onError);   stream.removeListener('end', done);  } })}
二,保证工具函数的回调在处理完毕数据后才被调用

工具函数往往会对外提供一个回调函数参数,待处理完流中的所有数据后,带着指定值触发,通常的做法是将回调函数的调用挂在流的end事件中,但如果处理函数是耗时的异步操作,回调函数则可能在所有数据处理完毕前被调用:

'use strict';const fs = require('fs');let stream = fs.createReadStream('/Path/to/a/big/file');function processSomeData (stream, callback) { stream.on('data', (data) => {  // 对数据进行一些异步耗时操作  setTimeout(() => console.log(data), 2000); }); stream.on('end', () => {  // ...  callback() })}processSomeData(stream, () => console.log('end'));
以上的代码callback回调可能会在数据并未被全部处理时就被调用,因为流的end事件的触发时机仅仅是在流中的数据被读完时。所以我们需要额外地对数据是否已处理完进行检查:

function processSomeData (stream, callback) { let count = 0; let finished = 0; let isEnd = false; stream.on('data', (data) => {  count++;  // 对数据进行一些异步耗时操作  setTimeout(() => {   console.log(data);   finished++;   check();  }, 2000); }); stream.on('end', () => {  isEnd = true;  // ...  check(); }) function check () {  if (count === finished && isEnd) callback() }}
这样一来,回调便会在所有数据都处理完毕后触发了。


  • 暂无相关文章
  • Posted in 未分类