이전에 쓴 글에 이어서 프로미스를 구현한 뒤 예제를 통해 동작을 확인해보겠습니다.

 

 

이전 포스트

https://ahat-li.tistory.com/24

 

프로미스 동작 분석하기(1)

자바스크립트 공부를 하다가 프로미스에 대해서 공부한 내용을 정리해볼까 한다. 프로미스가 내부에서 어떻게 동작하는지 프로미스를 간단하게 구현하고 예제를 통해 분석해보았다. 아래 코드

ahat-li.tistory.com

 

 

예제2)

new _Promise((res, rej) => {
     res(1);
})
.then((e) => {
     console.log("aa ", e);
     return e + 1
})
.then((e) => {
     console.log("bb ", e);
})

 

예제2는 예제1과 비슷하지만 프로미스 내부의 res 함수를 실행시키는 방법이 다릅니다.

예제 1은 setTimeout(() => { res(1)}, 3000); 이렇게 res 함수가 setTimeout 안에 들어있지만

예제 2에서는 res가 바로 실행되게 됩니다.

 

예제를 분석하여 어떤 방식으로 프로미스 동작이 이루어지는지 확인해보겠습니다.

우선 new 를 통해 첫번째 프로미스 객체가 생성됩니다.

그리하여 프로미스 생성자가 실행되는데 생성자 내부에서 인자로 받은 collback 함수 객체를 바로 실행합니다.

저 함수 객체는

(res, rej) => {

     res(1);

}

이런 객체인데 보시면 res 함수를 바로 실행시키고 있습니다.

res와 rej가 resolve, reject 함수과 연결되어 있기 때문에

res를 통해 첫번째 프로미스 객체의 resolve 함수가 바로 실행되게 됩니다.

 

resolve 메서드를 보면 프로미스 객체의 상태로 fulfilled로 변경하고있습니다.

프로미스1의 promiseResult에 res를 통해 전달된 1이라는 값이 들어갑니다

또한 프로미스1의 fulfilledFun 함수객체를 실행하게 되어있지만

프로미스1의 fulfilledFun가 undefined 이기 때문에 아무런 동작도 하지 않습니다.

프로미스 생성자의 모든 동작이 완료되었기 때문에 콜스택이 비워지게 됩니다.

 

 

이후 프로미스1의 메서드인 then이 실행됩니다.

예제1 에서는 then이 resolve보다 먼저 실행되었지만

예제2 에서는 then 보다 resolve가 먼저 실행되었다는 차이점이 있습니다.

 

그래서 then 메서드의 동작도 달라지는데요 프로미스1의 상태가 fulfilled이기 때문에 

return new _Promise(resolve =>   resolve(onFulfilled(this.promiseResult)));

이런 동작을 하게 됩니다.

 

 then의 메서드로 전달된 onFulfilled 함수 객체를 실행합니다.

then에 전달된 함수 객체는

(e) => {

     console.log("aa ", e);

     return e + 1

}

이런 모양을 하고 있습니다.

이 함수객체를 실행하기 때문에 aa 1 이라는 콘솔을 출력하고 2를 리턴하게 됩니다.

return new _Promise(resolve =>   resolve(2);

 

이제 then 메서드의 리턴값이 될 프로미스 객체를 생성하기 위해 

2번째 프로미스의 생성자를 실행하게 됩니다.

프로미스2의 상태값이 전달되고 프로미스2 생성자에 전달된 callback 함수객체를 바로 실행하게 됩니다.

프로미스2의 생성자에 전달된 callback 함수객체는

resolve =>   resolve(2) 이런 모양입니다.

callback 메서드를 바로 실행하기 때문에 프로미스2의 resolve 메서드가 실행되게 되는데 

여기서 프로미스2의 상태가 fulfilled로 바뀌고 promiseResult에는 2가 들어갑니다.

프로미스2의 fulfilledFun은 undefined 이기 때문에 아무런 동작도 하지 않습니다.

 

이후 프로미스2의 생성이 완료되고 콜스택은 다시 비워지게 됩니다.

 

 

 

다음은 프로미스2의 메서드인 then이 실행되게 됩니다.

전체적인 동작은 프로미스1의 then과 똑같습니다.

프로미스2의 상태가 fulfilled 인 상태에서 then 메서드가 실행되었기 때문에

then에 인자로 전달된 함수객체가 바로 실행되어 

bb 2 라는 콘솔 텍스트가 출력됩니다.

 

이후 프로미스3 객체가 생성되어 프로미스3의 생성자가 실행됩니다.

 

 

프로미스3의 생성자에 전달된 callback 함수에 의해서 프로미스3의 resolve 함수가 실행됩니다.

다만 프로미스3의 then 메서드가 실행되지 않기때문에 프로미스3의 생성자를 끝으로 예제2의 동작은 완료됩니다.

 

위에서 살펴본 내용을 요약하면 다음과 같이 볼 수 있을것 같습니다.

 

resolve 메서드가 then 메서드보다 먼저 실행될 경우

resolve 메서드가 실행된 시점에 프로미스 객체의 상태가 미리 fulfilled 상태로 변경되고

이후 then 메서드가 실행될 때 프로미스 객체의 상태가 fulfilled 일 때 인자로 들어온 함수 객체를 바로 실행시킴

이후 새로운 프로미스 객체를 생성하고 그 객체의 상태를 fulfilled 로 변경 후 리턴함

 

 

다만 자바스크립트 공식 프로미스에서도 저렇게 동작하는지는 나중에 제대로 확인을 해 보아야 할 것 같습니다...

 

이렇게 프로미스의 동작이 어떻게 이루어지는지 간단한 예제를 통해 알아보았는데

예제는 간단하지만 동작 자체는 상당히 복잡했습니다.

 

 

 

사실 위의 예제에서 사용하기 위해 구현한 프로미스 클래스에는 문제점이 있습니다.

프로미스 내부에서 저렇게  프로미스 객체를 생성하여 리턴하는 방식으로 

비동기 동작을 여러개 연결할 수 있습니다.

하지만 이번 예제를 위해 구현한 프로미스 클래스에서는 저런 방식의 동작이 불가능합니다...

 

이를 일부 함수동작을 바꾸는 것으로 동작하게 만들 수 있습니다.

다음 포스트에서는 일부 함수 내용을 수정하여 위와 같은 예제가 동작할 수 있도록 하겠습니다.

 

감사합니다.

+ Recent posts