>  기사  >  웹 프론트엔드  >  NODE.JS_node.js에서 스트림을 사용하여 도구를 작성할 때 주의할 사항

NODE.JS_node.js에서 스트림을 사용하여 도구를 작성할 때 주의할 사항

WBOY
WBOY원래의
2016-05-16 15:12:481006검색

Node.js의 스트림은 매우 강력하며 일부 시나리오에서는 잠재적으로 큰 파일 처리와 추상 데이터 처리 및 전달을 지원합니다. 사용하기가 너무 쉽기 때문에 실제 전투에서는 이를 기반으로 일부 도구 기능/라이브러리를 작성하는 경우가 많습니다. 그러나 스트림의 특정 특성을 무시한 경우 작성된 ​​기능/라이브러리가 어떤 경우에는 요구 사항을 충족하지 못할 수도 있습니다. . 원하는 효과를 얻거나 숨겨진 광산을 설치하세요. 이 기사에서는 스트림 기반 도구를 작성할 때 유용하다고 생각되는 두 가지 팁을 제공합니다.

1. EVENTEMITTER 메모리 누수에 주의하세요

여러 번 호출될 수 있는 함수에서 특정 작업을 수행하기 위해 스트림에 이벤트 리스너를 추가해야 하는 경우. 그런 다음 리스너 추가로 인해 발생하는 메모리 누수에 주의해야 합니다.

'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 함수는 스트림이 오류를 보고하거나 데이터가 없을 때 오류 이벤트 및 종료 이벤트를 수신하여 Promise를 완료합니다. 그러나 코드를 실행하면 곧 콘솔에 다음과 같은 경보 메시지가 표시됩니다. (노드) 경고: 가능한 EventEmitter 메모리 누수가 감지되었습니다. 11개의 오류 리스너가 추가되었습니다. 제한을 늘리려면 Emitter.setMaxListeners()를 사용하세요. 이 함수가 호출될 때마다 추가 오류 이벤트 리스너와 종료 이벤트 리스너가 수신 스트림에 추가됩니다. 이러한 잠재적인 메모리 누수를 방지하려면 각 함수 실행 후 이 호출로 추가된 모든 추가 리스너가 지워져 함수가 오염되지 않도록 해야 합니다.

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);
  }
 })
}

둘째, 데이터 처리 후 도구 함수의 콜백이 호출되는지 확인하세요

도구 함수는 종종 외부 세계에 콜백 함수 매개변수를 제공합니다. 스트림의 모든 데이터가 처리된 후 지정된 값으로 트리거됩니다. 일반적인 접근 방식은 스트림의 종료 이벤트에서 콜백 함수를 정지하는 것입니다. , 그러나 처리되는 경우 함수는 시간이 많이 걸리는 비동기 작업이므로 모든 데이터가 처리되기 전에 콜백 함수가 호출될 수 있습니다.

'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'));

스트림의 종료 이벤트는 스트림의 데이터를 읽을 때만 트리거되기 때문에 모든 데이터가 처리되지 않은 경우 위 코드 콜백이 호출될 수 있습니다. 따라서 데이터가 처리되었는지 추가로 확인해야 합니다.

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()
 }
}

이런 방식으로 모든 데이터가 처리된 후에 콜백이 실행됩니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.