1. Stream 주요 메서드 (이벤트)

on('data')
- 데이터 chunk 도착
- 자동으로 계속 전달됨
- 가장 많이 사용

on('end')
- 모든 데이터 읽기 완료
- 더 이상 읽을 데이터 없음

on('readable')
- 읽을 데이터가 준비됨
- 직접 stream.read() 호출해서 가져감
- data 보다 제어권이 많음

on('close')
- stream 종료
- 파일, 소켓 등 리소스 정리 완료
- 더 이상 이벤트 발생 안 함

on('error')
- 처리 중 오류 발생
- 언제든 발생 가능

흐름:

data
data
data
...
end
close

에러 발생 시:

data
data
error
close

구분:

data
→ 데이터 받기

readable
→ 데이터 받을 준비됨

end
→ 데이터 끝

close
→ 리소스 끝

error
→ 오류 발생

1-1. 기초 Readable

class MyStream extends Readable {
  #count = 0;
  _read(size) {
    this.push(':-)');
    if (++this.#count === 5) {
      this.push(null);
    }
  }
}

const stream = new MyStream({
  highWaterMark: 1,
});
stream.on('readable', () => {
  console.count('>> readable event');
  let chunk;
  while ((chunk = stream.read()) !== null) {
    console.log(chunk.toString()); // Process the chunk
  }
});
stream.on('end', () => console.log('>> end event'));

결과


>> readable event: 1
:-):-)
:-)
:-)
:-)
>> readable event: 2
>> readable event: 3
>> readable event: 4
>> end event

해설

호출 제어


class MyStream extends Readable {
  #count = 0;
  _read(size) {
    setImmediate(() => {
      this.push(':-)');
      if (++this.#count === 5) {
        return this.push(null);
      }
    });
  }
}

const stream = new MyStream({
  highWaterMark: 1,
});
stream.on('readable', () => {
  console.count('>> readable event');
  let chunk;
  while ((chunk = stream.read()) !== null) {
    console.log(chunk.toString()); // Process the chunk
  }
});
stream.on('end', () => console.log('>> end event'));

>> readable event: 1
:-)
>> readable event: 2
:-)
>> readable event: 3
:-)
>> readable event: 4
:-)
>> readable event: 5
:-)
>> readable event: 6
>> end event

1. on('readable') 등록
→ Node 내부 read(0)
→ _read(size)
→ setImmediate(push CB) 등록

2. check phase
→ push CB 실행
→ this.push(':-)')
→ 버퍼에 chunk 1개 저장
→ readable 이벤트 발생

3. readable listener 실행
→ console.count 출력

4. stream.read()
→ 버퍼에서 :-) 꺼냄
→ 버퍼가 highWaterMark 아래로 내려감
→ Node가 _read(size) 호출
→ setImmediate(push CB) 등록

5. console.log(':-)')

6. while 다음 반복
→ stream.read()
→ 아직 새 chunk 없음
→ null 반환
→ while 종료

7. 다음 check phase
→ push CB 실행
→ 반복

이상한점