request.on

zenibako.lee
6 min readOct 9, 2019

--

data event, stream in node.js 노드 스트림 이벤트 데이터

request.on (event(string), listener)

해당 메소드는 request instance에 ‘data’이벤트의 이벤트 핸들러(listener)를 bind해준다

request.on('data', chunk => {})

이 경우, request에서 ‘data’라는 이름의 event가 발생한 경우,

(chunk)=>{} 라는 이벤트 핸들러를 실행한다.

내가 이번 서버 만들기에서 실행했던 경우,

chunk는 Buffer object로 전달이 되었는데,

Buffer의경우 이후 개별 포스팅으로 따로 살펴보겠다.

그런데 ‘data’라는 이벤트는 언제 발생할까?

찾아보니

‘data’ event는 stream이 consumer에게 chunk of data의 소유권을 양도할 때 발생한다.

보다 구체적으로 보면,

  1. readable.pipe() 나 readable.resume()을 호출하거나
  2. ‘data’이벤트에 이벤트핸들러를 attach할 경우로 인해

‘스트림이 flowing mode로 변경된 경우’ 에 발생한다.

스트림은 뭐고 flowing mode는 또 무엇일까?

Stream

Stream은 Node.js의 data streaming에 사용되는 추상 인터페이스이다.

Stream모듈은 스트림 인터페이스를 구현하기 위한 api를 제공한다.

HTTP 서버로 보내는 request와 process.stdout 모두 stream모듈의 객체이다.

그리고 모든 stream은 EventEmitter의 객체이기도 하다.

-> 따라서 event emit이 가능하다

Stream 객체는

배열이나 문자열과 같은 데이터의 collection이다.

일반 객체와의 차이점은, 스트림을 한번에 모두 사용하지 않을 뿐더러, 메모리에 fit하지 않아도 된다는 것이다.

stream은 pipe()를 통해, chunk of data 단위로 쪼개져서 전송된다.

-> 순간 메모리 소모량의 대폭 감소, 비동기 방식으로 도착한 chunk순으로 먼저 처리 가능.

https://www.freecodecamp.org/news/node-js-streams-everything-you-need-to-know-c9141306be93/

Node.js의 모든 Stream은 event-driven 방식으로 설계, 작동된다!

Reading Modes

위에서 문제가 되었던 flowing mode가 무엇인지 알아보자.

Readable Stream들은 효과적으로 두가지 모드로 연산된다.

flowing과 paused이다.

flowing mode에서 data 는 기반시스템에서 자동으로 읽히고,
EventEmitter 인터페이스를 통해 발생시킨 이벤트를 통해
어플리케이션에 최대한 빨리 해당 data를 전달한다.

flowing mode에서 처리할 수 있는 consumer가 없는 경우, 데이터가 손실될 수 있다.

따라서, flowing mode의 readable stream이 있을 때, ‘data’ event handler가 필요하다. 실제로, data event handler를 추가하면, 일시정지된 스트림이 flowing mode로 switch되고, 해당 핸들러를 제거하면, 스트림이 다시 paused모드로 돌아간다.

매우 산만한 정리였지만,

결론적으로 request.on()을 다시 정리해보자면,

readable stream인 request에 ‘data’ event의 event handler를 할당한다.

그 결과, request는 flowing mode로 switch, ‘data’이벤트가 발생한다 -> 재귀로 stream의 chunk들을 계속 받게 되고

stream 의 모든 chunk가 소진되면, ‘end’이벤트가 발생, flowing mode에서 paused모드로 전환되며, 데이터 전송이 완료된다.

+API for Stream Consumers

const http = require('http');

const server = http.createServer((req, res) => {
// `req` is an http.IncomingMessage, which is a Readable Stream.
// `res` is an http.ServerResponse, which is a Writable Stream.

let body = '';
// Get the data as utf8 strings.
// If an encoding is not set, Buffer objects will be received.
req.setEncoding('utf8');

// Readable streams emit 'data' events once a listener is added.
req.on('data', (chunk) => {
body += chunk;
});

// The 'end' event indicates that the entire body has been received.
req.on('end', () => {
try {
const data = JSON.parse(body);
// Write back something interesting to the user:
res.write(typeof data);
res.end();
} catch (er) {
// uh oh! bad json!
res.statusCode = 400;
return res.end(`error: ${er.message}`);
}
});
});

server.listen(1337);

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

zenibako.lee
zenibako.lee

Written by zenibako.lee

backend engineer, JS, Node, AWS

No responses yet

Write a response