오늘은 js에서 프로미스 문법이 나오게된 이유 중 하나인 콜백함수, 프로미스 에서의 비동기 함수의 에러처리에 대해 정리해보겠습니다 :)


콜백함수와 비동기 함수의 에러처리

아래 코드는

1000ms의 시간이 흐른후 새로 생성한 Error가 catch문법에서 잡히고 에러메시지를 콘솔에 출력하기를 기대하고 작성했습니다.

try {
	setTimeout(() => {throw new Error('Error!');}, 1000);
} catch (e) {
    console.log('error!!!!')
	console.error('캐치한 에러', e);
}

하지만 위 코드는 의도대로 실행되지 않습니다.


의도 대로 실행된다면

아래와 같은 결과를 콘솔에 출력할것입니다.

캐치한 에러 Error: Error!
    at Timeout._onTimeout (/Users/test.js:5:20)
    at listOnTimeout (internal/timers.js:557:17)
    at processTimers (internal/timers.js:500:7)

 

의도와 다르게 실행되는 이유는 js에서의 비동기 함수와 콜백함수의 동작과정에 있습니다.

위 코드의 동작과정을 아래 그림과 함께 살펴보면 4단계로 나눌 수 있습니다.

 

 

1. 비동기 함수인 setTimeout이 호출되면 setTimeout 함수의 실행 컨텍스트가 생성되어 콜 스택에 푸시되어 실행

2. setTimeout은 비동기 함수이므로 콜백 함수가 호출되는 것을 기다리지 않고 즉시 종료되어 콜 스택에서 제거

3. setTimeout에서 설정된 시간이 지나면 setTimeout함수의 콜백 함수는 태스크 큐로 푸시

4. 콜 스택이 비어있을 때 이벤트 루프에 의해 콜 스택으로 푸시되어 실행

 

setTimeout함수의 콜백 함수를 sq라고 하겠습니다.

 

4번 과정에서 sq가 실행됩니다.

하지만 setTimeout함수는 이미 콜 스택에서 제거된 상태이므로 sq를 호출한 것은 setTimeout가 아니라는 의미입니다.

 

그리고 js에서 에러는 호출자 방향으로 전파됩니다.

결국 sq의 에러가 setTimeout함수로 전파되지 않았기 때문에 의도한 대로 동작하지 않았다는 거죠

 

콜백함수를 사용한 에러핸들링 예시는 링크를 통해 확인해볼 수 있습니다.

 

 

 

프로미스와 비동기 함수의 에러처리

프로미스를 사용하면 아래와 같이 reject를 이용하여 에러 핸들링이 가능합니다.

const sleep = async function sleep(ms) {
    return new Promise(function(resolve,reject){
        console.log('프로미스 생성중!')
        setTimeout(() => {
            reject(new Error('async operation failure!'));
        },1000)
    })
  }

async function test() {
	console.log('aa');
	await sleep(3000)
    .catch(e => {
        console.error('캐치한 에러', e);
    });
	console.log('bb');
}

test()

 

 

위 코드와 콜백함수를 사용한 에러처리 예시 링크의 코드를 비교해보면 
Promise문법에 비해 많은 함수와 문법을 사용해야해 간결하지 못한 코드를 확인할 수 있습니다.

 

 

반응형

+ Recent posts