Javascript 와 Promise
자바스크립트를 처음부터 다시 공부해보려고 한다.
computer science 에서는 보통 동기 프로그램을 작성할 때 future, promise, delay, deferred 로 아직 실행되지 않은 구문을 작성한다.
웹에서 요청과 응답 이 많아 지면서, 동기 프로그램을 작성해야 하는 상황이 많이 발생하였다.
이를 해결하기 위해 ECMAScript6 부터 Promise 패턴이 추가되었다.
Promise 는 Promises/A+ 표준 으로 작성되었다.
Promise 는 3가지 상태가 존재한다.
- pending : 대기상태
- fulfilled : 성공상태
- rejected : 실패상태
Promise
Promise 는 생성자를 이용해서 생성할 수 있으며, 인자로 반드시 function 을 받아야 한다.
new Promise ( function 함수( resolve, reject ) );
인자를 받지 않거나 함수이외의 값을 전달하면, Uncaught TypeError 가 발생한다.
만약 인자로 전달된 resolve 와 reject 중 하나라도 호출하지 않는다면, 영원히 pending 상태로 대기한다.
Then
Promise.prototype.then 은 promise 의 resolve 결과를 chaining 으로 연속적인 처리가 가능하다.
인자로 2개의 함수 (resolve, reject) 를 받을 수 있으며, 반환자는 Promise 이다. 때문에 반환받은 promise 를 다시 then 으로 chaining 할 수 있다.
promise.then(function(value){fulfilled}, function(error){rejected})
만약 return 이 없다면, 다음 then 은 value를 undefined 를 가진 promise 를 전달 받는다.
항상 새로운 promise 를 받기 때문에 이전 promise 의 값은 영향을 받지 않는다.
만약 참조 형을 전달하고, 중간에 참조형의 프로퍼티를 변경 할 경우 원 promise 의 resolve 값이 영향을 받는다.
Catch
Promise.prototype.catch 은 promise 의 reject 이나 throw Error 의 값을 받는다.
중간의 then 에서 onRejected 를 처리한다면, catch 는 무시된다.
return promise
만약 then 의 return 이 promise 라면 resolve, reject 의 처리 결과를 반환한다.
then 은 전달하는 값이 promise 가 아니라면 promise 로 래핑해서 반환한다.
반환 값이 promise 라면 해당 promise 를 반환한다.
Promise 메서드
Promise.reject
와 Promise.resolve
는 즉시 실행되는 Promise 를 만들 수 있다.
then 으로 체이닝 할경우, resolve 는 onFulfilled
영역을 reject 는 onRejected
영역이 호출된다.
Promise.all
Promise.all 은 모든 Promise 가 resolve 된 이후의 resolve 를 배열로 반환한다.
만약 주어진 Promise 중 하나의 Promise 라도 reject 이 발생된다면, 가장 먼저 reject 된 값을 reject 으로 반환한다.
Promise.all 은 iterable 값을 인자로 받기 때문에, Promise 가 아니더라도 래핑해서 Promise 로 처리한다.
Promise.race
전달된 Promise 들 중 가장 빨리 resolve 나 resolve 된 값을 반환한다.
promise.race 는 iterable 값을 인자로 받기 때문에, Promise 가 아니더라도 래핑해서 Promise 로 처리한다.
하지만 그럴 경우 즉시 반환되기 때문에 race 를 쓰는 의미가 없어진다.
Promise 스케줄
Javascript 의 Event loop 는 Call stack 과 Queue (task queue, microtask queue) 사이의 작업들을 확인하여 처리한다.
promise 의 then 작업들은 microtask queue 에 등록되어 처리된다.
- 작업을 만나면 call stack 에 넣는다.
- call stack 에서 작업을 꺼내고 처리한다.
- 처리중 callback 을 만나면, task queue 에 등록한다.
- promise 를 만나면, call stack 에 넣는다.
- call stack 에서 promise 작업을 꺼내고 처리한다.
- 이때 then 을 만나면, microtask queue 에 등록한다.
- 모든 스크립트의 call stack 작업이 끝나면, 우선적으로, microtask queue 를 확인하고 call stack 에 넣는다.
- call stack 에서 작업을 꺼내고 처리한다.
- microtask queue 작업이 없다면, task queue 를 확인하고 Call stack 에 넣는다.