成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

使用 Node.js 中的流寫工具時(shí)的兩點(diǎn)小 tips

fizz / 3438人閱讀

摘要:中的流十分強(qiáng)大,它對處理潛在的大文件提供了支持,也抽象了一些場景下的數(shù)據(jù)處理和傳遞。本文將會(huì)提供兩個(gè)在編寫基于流的工具時(shí),私以為有些用的兩個(gè)。

Node.js中的流十分強(qiáng)大,它對處理潛在的大文件提供了支持,也抽象了一些場景下的數(shù)據(jù)處理和傳遞。正因?yàn)樗绱撕糜?,所以在?shí)戰(zhàn)中我們常?;谒鼇砭帉懸恍┕ぞ?函數(shù)/庫 ,但往往又由于自己對流的某些特性的疏忽,導(dǎo)致寫出的 函數(shù)/庫 在一些情況會(huì)達(dá)不到想要的效果,或者埋下一些隱藏的地雷。本文將會(huì)提供兩個(gè)在編寫基于流的工具時(shí),私以為有些用的兩個(gè)tips。

一,警惕EventEmitter內(nèi)存泄露

在一個(gè)可能被多次調(diào)用的函數(shù)中,如果需要給流添加事件監(jiān)聽器來執(zhí)行某些操作。那么則需要警惕添加監(jiān)聽器而導(dǎo)致的內(nèi)存泄露:

"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函數(shù)會(huì)在通過監(jiān)聽error事件和end事件,來在流報(bào)錯(cuò)或沒有數(shù)據(jù)時(shí),完成這個(gè)Promise。然而在執(zhí)行代碼時(shí),我們很快就會(huì)在控制臺(tái)中看到報(bào)警信息:(node) warning: possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit.,因?yàn)槲覀冊诿看握{(diào)用該函數(shù)時(shí),都為傳入的流添加了一個(gè)額外的error事件監(jiān)聽器和end事件監(jiān)聽器。為了避免這種潛在的內(nèi)存泄露,我們要確保每次函數(shù)執(zhí)行完畢后,清除所有此次調(diào)用添加的額外監(jiān)聽器,保持函數(shù)無污染:

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);
    }
  })
}
二,保證工具函數(shù)的回調(diào)在處理完畢數(shù)據(jù)后才被調(diào)用

工具函數(shù)往往會(huì)對外提供一個(gè)回調(diào)函數(shù)參數(shù),待處理完流中的所有數(shù)據(jù)后,帶著指定值觸發(fā),通常的做法是將回調(diào)函數(shù)的調(diào)用掛在流的end事件中,但如果處理函數(shù)是耗時(shí)的異步操作,回調(diào)函數(shù)則可能在所有數(shù)據(jù)處理完畢前被調(diào)用:

"use strict";
const fs = require("fs");

let stream = fs.createReadStream("/Path/to/a/big/file");

function processSomeData (stream, callback) {
  stream.on("data", (data) => {
    // 對數(shù)據(jù)進(jìn)行一些異步耗時(shí)操作
    setTimeout(() => console.log(data), 2000);
  });

  stream.on("end", () => {
    // ...
    callback()
  })
}

processSomeData(stream, () => console.log("end"));

以上的代碼callback回調(diào)可能會(huì)在數(shù)據(jù)并未被全部處理時(shí)就被調(diào)用,因?yàn)榱鞯?b>end事件的觸發(fā)時(shí)機(jī)僅僅是在流中的數(shù)據(jù)被讀完時(shí)。所以我們需要額外地對數(shù)據(jù)是否已處理完進(jìn)行檢查:

function processSomeData (stream, callback) {
  let count = 0;
  let finished = 0;
  let isEnd = false;

  stream.on("data", (data) => {
    count++;
    // 對數(shù)據(jù)進(jìn)行一些異步耗時(shí)操作
    setTimeout(() => {
      console.log(data);
      finished++;
      check();
    }, 2000);
  });

  stream.on("end", () => {
    isEnd = true;
    // ...
    check();
  })

  function check () {
    if (count === finished && isEnd) callback()
  }
}

這樣一來,回調(diào)便會(huì)在所有數(shù)據(jù)都處理完畢后觸發(fā)了。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/78777.html

相關(guān)文章

  • [轉(zhuǎn)]nodejs Stream使用手冊

    摘要:方法也可以接收一個(gè)參數(shù)表示數(shù)據(jù)請求著請求的數(shù)據(jù)大小,但是可讀流可以根據(jù)需要忽略這個(gè)參數(shù)。讀取數(shù)據(jù)大部分情況下我們只要簡單的使用方法將可讀流的數(shù)據(jù)重定向到另外形式的流,但是在某些情況下也許直接從可讀流中讀取數(shù)據(jù)更有用。 介紹本文介紹了使用 node.js streams 開發(fā)程序的基本方法。 We should have some ways of connecting programs ...

    luffyZh 評論0 收藏0
  • 《java 8 實(shí)戰(zhàn)》讀書筆記 -第四章 引入流

    摘要:第四章引入流一什么是流流是的新成員,它允許你以聲明性方式處理數(shù)據(jù)集合通過查詢語句來表達(dá),而不是臨時(shí)編寫一個(gè)實(shí)現(xiàn)。 第四章 引入流 一、什么是流 流是Java API的新成員,它允許你以聲明性方式處理數(shù)據(jù)集合(通過查詢語句來表達(dá),而不是臨時(shí)編寫一個(gè)實(shí)現(xiàn))。就現(xiàn)在來說,你可以把它們看成遍歷數(shù)據(jù)集的高級迭代器。此外,流還可以透明地并行處理,你無需寫任何多線程代碼。 下面兩段代碼都是用來返回低...

    jeyhan 評論0 收藏0
  • 正在暑假中的《課多周刊》(第1期)

    摘要:正在暑假中的課多周刊第期我們的微信公眾號,更多精彩內(nèi)容皆在微信公眾號,歡迎關(guān)注。若有幫助,請把課多周刊推薦給你的朋友,你的支持是我們最大的動(dòng)力。原理微信熱更新方案漲知識了,熱更新是以后的標(biāo)配。 正在暑假中的《課多周刊》(第1期) 我們的微信公眾號:fed-talk,更多精彩內(nèi)容皆在微信公眾號,歡迎關(guān)注。 若有幫助,請把 課多周刊 推薦給你的朋友,你的支持是我們最大的動(dòng)力。 遠(yuǎn)上寒山石徑...

    liukai90 評論0 收藏0
  • 正在暑假中的《課多周刊》(第1期)

    摘要:正在暑假中的課多周刊第期我們的微信公眾號,更多精彩內(nèi)容皆在微信公眾號,歡迎關(guān)注。若有幫助,請把課多周刊推薦給你的朋友,你的支持是我們最大的動(dòng)力。原理微信熱更新方案漲知識了,熱更新是以后的標(biāo)配。 正在暑假中的《課多周刊》(第1期) 我們的微信公眾號:fed-talk,更多精彩內(nèi)容皆在微信公眾號,歡迎關(guān)注。 若有幫助,請把 課多周刊 推薦給你的朋友,你的支持是我們最大的動(dòng)力。 遠(yuǎn)上寒山石徑...

    yintaolaowanzi 評論0 收藏0
  • Gulp思維——Gulp高級技巧

    摘要:我們創(chuàng)建一個(gè)可讀流,并嘗試使用和來進(jìn)行轉(zhuǎn)換,將最后得到的內(nèi)容交給。它重新使用可讀流中的文件名,然后在必要時(shí)創(chuàng)建文件夾使用。使用常規(guī)可讀流時(shí),你可以監(jiān)聽事件來檢測數(shù)據(jù)碎片的到來不同的是,使用會(huì)將轉(zhuǎn)換成的文件對象重新寫入到流中。 本文翻譯自Getting gulpy -- Advanced tips for using gulp.js 感受過gulp.js帶來的興奮過后,你需要的不僅僅是...

    ad6623 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<