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
→ 오류 발생
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 실행
→ 반복
stream.read() === null vs this.push(null)