동글이의 STORY
콜백 패턴 본문
728x90
반응형
🔷Callback 패턴?
function foo(callback) {
const a = 10;
const b = 20;
callback(a, b);
}
function boo(a, b) {
return a + b;
}
foo(boo);
- 콜백은 함수에 인자로 넣어지는 함수
- 자바스크립트에선 함수 자체가 객체이기 때문에 함수의 인자로 넣어 줄 수 있음
🔷Callback 을 사용한 비동기 처리
function squareAndCallBack(number) {
let square;
setTimeout(() => {
square = number * number
}, 100);
console.log(square);
}
squareAndCallBack(2);
// undefined
- 자바스크립트는 setTimeout을 기다려주지 않는다 WebAPI를 호출해 task queue로 넘긴다
- 바로 콘솔로그를 실행하고 setTimeout의 로직을 실행하기 때문에 square는 undefined이다.
- setTimeout은 addAsync로 제어를 돌려주어 제어가 호출자에게 반환됨.
- 호출 시점의 컨텍스트를 유지하는 것은 Closure의 특성 덕분
function squareAndCallBack(number, callback) {
setTimeout(() => {
const square = number * number
callback(square)
}, 100);
}
function consolePrint(value) {
console.log(value);
}
squareAndCallBack(2, consolePrint);
// 4
- 위와 같은 비동기 문제를 해결하기 위해 콜백을 사용할 수 있다.
- setTimeout로직 안에 콜백함수를 넣어주면 로직이 실행된뒤 콜백을 통해 결과를 가지고 무언가를 할 수 있다.
🔷Callback 규칙
- 콜백은 맨 마지막에, 오류는 맨 앞에
fs.readFile('foo.txt', (err, data, callback) => { if(err) handleError(err); else { callback(data); } })
- ex)
- 오류 전파
- 일반적으로 비동기식 CPS에서 오류를 callback으로 전달하여 수행
- 오류를 전달할 때는 return callback(err) 처럼 사용해 early return
- 캐치되지 않는 예외
- uncaughtException은 어플리케이션의 일관성을 보장할 수 없게 만든다. 비동기 콜백 내부에서 예외를 발생시키면, 그 예외는 이벤트 루프로 이동한다.
- 위의 예에서 만약 try... catch 구문이 없고 JSON.parse 에서 에러가 발생한다면, 예외가 그대로 이벤트 루프로 이동하고 다음 콜백으로 전파되지 않는다.(위의 그림 참고)
- 제대로 된 예외를 받고자 한다면, 예외가 발생한 스택과 실행 스택이 같아야한다. 즉, 위와같이 에러가 발생할만한 비동기 코드 내부에서 try catch 로 감싸야 한다.
- 위의 예시를 기준으로, try ... catch 스택과 parse((err, data) => { })의 스택은 별개의 스택
- ... try { const parsed = JSON.parse((err, data) => { ... }); } catch { // Error catch return callback(err); } ...
- 그런데, uncaughtException이 만약 발생한다면, 어쨌든 어플리케이션을 종료하도록 처리하는 것이 좋다.
- uncaughtException은 어플리케이션의 일관성을 보장할 수 없게 만든다. 비동기 콜백 내부에서 예외를 발생시키면, 그 예외는 이벤트 루프로 이동한다.
🔷Async Await와 관련된 처리되지 않는 에러
- 테스트 코드 작성 중 아래와 같은 테스트가 실패한 이유?
expect(await funcThrowException()).to.be.rejectedWith(..);
// 이렇게 보면 편하다.
expect(
// ..
await funcThrowException
// ..
).to.be.rejectedWith(..);
- await 키워드를 만나는 시점에 백그라운드로, 이후에 queue로 들어가지만 다시 call stack에 들어간 시점에 funcThrowExecption에서 던진 에러를 어디에서도 받지 못한다.
- 바깥의 블락(expect ... to.be.rejectedWith)에서 try ... catch로 감싸주면 에러를 잡을 수 있게 된다.
728x90
반응형
'Javascript > 자바스크립트 패턴' 카테고리의 다른 글
싱글톤 패턴 (0) | 2024.07.03 |
---|---|
메모이제이션 패턴 (2) | 2024.07.03 |
고차함수 / 커링 / 부분적용함수 (5) | 2024.07.03 |
클로저 (3) | 2024.07.03 |
프라미스 패턴 (0) | 2024.07.03 |