Promise 오브젝트 -ECMAScript
Promise
오브젝트는 비동기(Asynchronous
)처리를 위한 메커니즘을 제공합니다.ES5
까지 없었던 개념으로 ES6
에 추가되었습니다.
- Promise 오브젝트
- 개요
- Promise 처리 순서
- Promise 상태
- settled 상태
- fulfill (성공)
- reject (실패)
- new Promise(): Promise 인스턴스 생성
- then(): 성공, 실패 핸들러
- catch(): 실패 핸들러
- resolve(): 성공 상태의 인스턴스 반환
- thenable
- reject(): 실패 상태의 인스턴스 반환
- all(): 모두 성공이면 핸들러 실행
- race(): 처음 한 번만 핸들러 호출
- 개요
개요
자바스크립트는 기본적으로 동기(Synchronous
)로 실행합니다. 동기 실행이란 현재 코드가 실행을 완료해야 다음 코드가 실행되는 것을 의미합니다. 여러 줄의 코드가 있다고 했을 때, 첫째 줄의 코드가 실행을 완료해야 둘째 줄이 실행되며, 둘째 줄이 실행을 완료해야 셋째 줄이 실행되는 형태입니다.
반면, Promise
는 비동기(Asynchronous
)로 실행합니다. XMLHttp Request
의 비동기 통신과 비슷합니다.
클라이언트에서 서버로 보낸 요청(Request
)에 서버가 응답(Response
)할 때까지 통신이 연결된 상태에서 기다리지 않습니다. 따라서 서버가 처리하는 동안 다른 처리를 할 수 있습니다. 클라이언트에서 서버가 응답했을 때의 처리를 사전에 정의해 두면, 서버가 응답했을 때 정의한 코드가 자동으로 실행됩니다.
Promise
도 이와 개념이 비슷합니다.
코드 구현 관점에서 보면 Promise
는 하나의 오브젝트입니다.Promise
오브젝트에서 비동기 처리 방법을 제공하므로 이에 맞추어 코드를 작성하면 됩니다.
Promise
오브젝트는 DOM
(Document Object Model)에서 처음 제시되었으나 현재는 JavaScript
스펙에 포함되었습니다. 따라서 DOM
에서도 사용이 가능하며 이는 DOM
을 사용하는 다른 언어에서도 Promise
를 사용할 수 있다는 것이 됩니다.
Promise 처리 순서
Promise
개념을 이해하기 위해 Promise
의 비동기 처리 흐름을 간단하게 살펴봅니다.
1 | 1. function create(){ |
- 엔진이
function
키워드를 만나면create()
를 호출할 수 있도록Function
오브젝트로 생성합니다.
함수 안에 코드는 실행하지 않고 다음 줄로 이동합니다.
create()
함수를 호출합니다. 함수 안에 코드가 실행됩니다.
return
문의 표현식을 평가하므로new Promise()
로 인스턴스를 생성합니다.이때,
Promise()
파라미터에 작성한function(){}
을 실행합니다. (function을 executer(실행자)라고 합니다.)function
(executer) 블록의 첫째 줄에resolve()
가 작성되어 있습니다. 그런데 호출을 받아서 처리할 같은 이름의 함수가 소스 코드에 없습니다. 단지 파라미터에resolve
가 작성되어 있을 뿐입니다.resolve()
형태가 함수를 호출하는 형태이지만 호출하지 않습니다. 이에 대해서는 사전 설명이 필요하므로 뒤에서 다룹니다.다음 줄에 console.log()를 실행하여 “1: resolve”를 출력합니다.
생성한 인스턴스를 반환합니다.
여기서 중요한 점이executer
가 실행된다는 것과resolve
()가 호출되지 않는다는 점입니다. resolve()를 바로 호출하지 않고 호출할 수 있는 환경이 되었을 때 호출합니다.
create()
실행이 끝나면 생성한Promise
인스턴스를 반환합니다.Promise
인스턴스에then()
이 있으므로 이어서then()
을 호출할 수 있습니다. 하지만then()
을 호출하지 않고, 아래 코드로 이동합니다.
앞에서resolve()
를 호출할 수 있는 환경이 되었을 때 호출하는 것과then()
을 실행하지 않고 아래 코드로 이동하는 것이Promise
비동기 처리의 핵심 매커니즘 입니다.
create()
실행 이후에then()
을 호출하지 않고 다음 줄로 이동했을 때 만나는 코드입니다.
“2: 끝”이 출력됩니다. 이제 더 이상 남아있는 코드가 없습니다.
- 이제 남은 것은
then()
에 작성한function()
의 실행입니다.then()
은 두 개의 파라미터를 갖고 있습니다.
위 코드에서는 첫 번째 파라미터의function
이 실행되어“3: 성공”
이 출력됩니다.
두 번째 파라미터의function
은 실행되지 않습니다. 첫 번째 파라미터function
이 실행된 이유는 뒤에서 다룹니다.
console.log 출력 순서를 보면
“1: resolve”는 new Promise()로 인스턴스를 생성할 때 executer에서 출력합니다.
Promise 인스턴스를 생성해야 메서드를 사용할 수 있으므로 먼저 인스턴스를 생성합니다.“2: 끝”은 create()에 연결된 then()을 실행하지 않으므로 두 번째로 실행됩니다.
“3: 성공”은 소스 코드 전체를 끝까지 처리한 후 실행되어 세 번째로 출력됩니다.
Promise 상태
Promise
는 코드를 실행할 때마다 진행 상태를[[PromiseState]]
에 저장합니다.
상태를 저장하는 이유는 연속해서 코드를 실행하지 않고, 소스 코드 끝까지 내려갔다 다시 올라와서 실행하므로 진행 상태가 필요하기 때문입니다. 상태에 따라 다음 단계를 처리하기 위해서 입니다.
Promise
진행 상태는 크게 두 가지로 나눌 수 있습니다.pending
과 settled
로 나뉩니다.settled
상태는 다시 fulfill
(성공) 과 reject
(실패)로 나눌 수 있습니다.pending
과 settled
는 상태이면서 발생 단계입니다. 먼저 pending
상태가 되었다가 settled
상태로 넘어갑니다.
단계로 보면 두 단계 (pending
, settled
)이지만 상태 측면에서 보면 세 개이므로 세 개의 상태로 분류하기도 합니다.
pending 상태
1 | function create(){ |
pending
상태(단계)에서는 위 코드와 같이 우선 new Promise()
로 인스턴스를 생성합니다. 그리고 executer
를 실행하여 성공과 실패에 따라 호출할 핸들러 함수를 바인딩 합니다.
바인딩이란 resolve()
와 같이 바로 함수를 호출하지 않고 나중에 호출하므로, 그때를 위한 호출 환경을 설정하는 것을 의미합니다.
executer
블록의 코드를 실행하지 않고 소스 코드 끝까지 처리한 후 실행하므로 이 시점에서 Promise
처리의 성공과 실패를 알 수 없습니다. 따라서 성공 또는 실패가 발생했을 때, 이에 따라 함수가 호출될 수 있도록 환경 설정이 필요합니다.
settled 상태
1 | create().then(function(){ |
pending
상태가 종료되면 settled
상태로 변환됩니다. 이때 처리의 성공과 실패를 알 수 있습니다.settled
상태는 다시 fulfill
(성공) 상태와 reject
(실패) 상태로 구분됩니다. 상태에 따라 pending
단계에서 바인딩한 핸들러 함수가 호출됩니다.
fulfill (성공)
executer
불록의 코드가 성공적으로 실핸된 상태를 나타냅니다.then()
의 첫 번째 파라미터의 핸들러(function
)가 실행됩니다. - 핸들러 안에 성공에 따른 코드를 작성합니다.
reject (실패)
executer
블록의 코드 실행이 실패한 상태를 나타냅니다.then()
의 두 번째 파라미터의 핸들러가 실행됩니다. - 핸들러 안에 실패에 따른 코드를 작성합니다.
new Promise(): Promise 인스턴스 생성
Promise
인스턴스를 생성하여 반환합니다.
new Promise()
1 | new Promise(function(resolve, reject){ |
executer
에 두 개의 파라미터를 작성할 수 있습니다. 첫 번째 파라미터에executer
블록에서 처리를 성공했을 때 호출할 핸들러 이름(resolve)를 작성합니다. 두 번째 파라미터에 실패했을 때 호출할 핸들러 이름(reject
)를 작성합니다.resolve
와reject
는 가독성을 위한 것으로 다른 이름을 사용해도 됩니다.
executer
블록에 핸들러 함수를 작성하지 않으면, then()의 파라미터에 작성한 함수가 실행되지 않습니다.
핸들러 함수 이름과executer
의 파라미터에 작성한 이름과 같아야 하며, 같지 않으면 에러가 발생합니다.
예를 들어,resolve()
와function(resolve)
와 같이resolve
이름이 같아야 합니다.
성공 기준
1 | function create(param){ |
create()
를 호출하면서 “ok”를 파라미터 값으로 넘겨 줍니다. 호출받은create()
함수의 파라마터param
에 설정됩니다.
executer
의 파라미터에resolve
와reject
를 작성했습니다.Function
오브젝트를 생성하여resolve
와reject
에 할당합니다.Promise
인스턴스를 생성하여return
한 후,create()
에 연결된then()
의 파라미터에 작성한 함수와 연결합니다.이렇게 설정함으로써
executer
블록에서resolve()
를 호출하면then()
의 첫 번째 파라미터의 함수가 호출되고,reject()
를 호출하면then()
의 두 번째 파라미터의 함수가 호출됩니다.executer
파라미터의resolve
와executer
블록의resolve()
와then()
의 첫 번째 파라미터 함수가 연결되고,executer
파라미터의reject
와executer
블록의reject()
와then()
의 두 번째 파라미터 함수가 연결되는 것입니다.
param
값으로 받은 파라미터가 “ok”이므로 true가 되어 if 문 블록을 수행합니다.resolve(param)
가 함수를 호출하는 형태이지만, 지금 호출하지 않고 소스 코드를 끝까지 실행한 후 되돌아와서 호출합니다. 되돌아와서resolve()
를 호출하면 이를 받아 실행할 같은 이름의 함수가 없습니다.이때 executer 파라미터의 resolve에 설정된 함수를 호출합니다. 그러면 resolve 와 then()의 첫 번째 파라미터의 함수와 연결되어 있으므로 then()의 첫 번째 함수가 연결되어 있으므로 then()의 첫 번째 함수가 실행됩니다. 이것이 Promise의 비동기 처리 메커니즘입니다.
resolve(param)
다음 줄에 console.log을 실행하며 “1: resolve”를 출력합니다.
이제 남은 것은 생성한 인스턴스를 반환하는 것입니다.
create(“ok”)
의 호출이 완료되면Promise
인스턴스를 반환하므로“인스턴스.then()”
형태가 되어then()
을 실행할 수 있지만 바로 실행하지 않습니다. 우선then()
의 첫 번째 파라미터를executer
의resolve
에 바인딩하고,then()
의 두 번째 파라미터를executer
의reject
에 바인딩 합니다.이렇게 바인딩을 함으로써
executer
블록에서resolve()
를 호출했을 때then()
의 첫 번째 파라미터에 작성한 함수가 실행됩니다.
- 소스 코드의 마지막 코드로 console에 “2: 끝”을 출력합니다. 모든 코드를 읽었으므로 이제 남은 것은
resolve()
를 실행하는 것입니다.
executer
블록에서resolve(param)
을 호출하면,then()
의 첫 번째 파라미터 함수가 호출됩니다.
이때,resolve(param)
에서param
값인 “ok”가 핸들러 함수인function(param)
의param
에 설정됩니다.
따라서 console에 “3: 성공, ok”가 출력됩니다.
실패 기준
1 | function create(param){ |
- 바로 앞에서 다룬 코드는 성공 기준이며 위 코드는 실패 기준입니다.
Promise
처리 흐름은 같습니다.then()
의 두 번째 파라미터에 작성한 함수가 실행된다는 점이 다릅니다.
create()
를 호출하면서“fail”
을 파라미터 값으로 넘겨 줍니다.
호출된create()
함수에서if
문의else
블록reject(param)
과console.log(“1: reject”)
를 실행하게 됩니다.물론
reject(param)
은 이때 호출되지 않고 소스 코드를 끝까지 실행한 후 되돌아와서 호출 환경이 설정되있을 때 호출됩니다.executer
블록에서reject()
가 호출되면then()
의 두 번째 파라미터에 작성한 함수가 실행됩니다.
따라서 콘솔에 “3: 실패, fail”이 출력됩니다.
then(): 성공, 실패 핸들러
성공과 실패 핸들러를 정의합니다.
Promise.prototype.then(onFulfilled, onRejected)
첫 번째 파라미터에 Promise
가 성공 상태가 되었을 때 실행될 핸들러 함수를 작성합니다.
두 번째 파라미터에 Promise
가 실패 상태가 되었을 때 실행될 핸들러 함수를 작성합니다.
executer
블록의resolve()
와reject()
에서 다수의 파라미터 값을 넘겨주더라도 핸들러 함수에서 첫 번째 파라미터 하나만 받습니다. 따라서 여러 개의 파라미터 값을 넘겨 주려면resolve()
와reject()
의 파라미터에 배열과 같은 형태로 작성해야 합니다.
resolve
(성공) 와reject
(실패) 핸들러 함수에서return
문의 작성 여부와 관계없이 현재 실행 중인Promise
인스턴스를 반환합니다.return
문을 작성하면return
문의 표현식을 평가하고 그 결과를[[PromiseValue]]
에undefined
를 설정합니다.
then()
에서Promise
인스턴스를 반환하므로then(one).then(two)
와 같이then()
을 연속해서 작성할 수 있습니다. 이때, 첫 번째then()
에서[[PromiseValue]]
에 설정한 값이 두 번째then(two)
의 파라미터인two
에 설정됩니다. 핸들러 함수에서Promise
인스턴스를 반환하여 연속해서 메서드를 호출할 수 있도록 하고,return
문의 반환 값을[[PromiseValue]]
에 설정하여 다음then()
의 핸들러 함수의 파라미터에 설정합니다.
1 | 1. function create(){ |
create()
가 호출되면executer
블록의resolve()
를 수행하게 됩니다.
하지만 호출받을resolve
함수가 없으므로 호출 환경이 되었을 때 호출합니다.
즉, 소스 코드 끝까지 처리하고 되돌아와 호출합니다.
실패가 발생하지 않으면executer
의 파라미터와 블록에reject
를 작성하지 않아도 됩니다.
then()
의 첫 번째 파라미터에 핸들러 함수를 작성하여 연결합니다.executer
블록에서resolve
파라미터 값으로 100을 넘겨 주지만 이 코드에서는 사용되지 않습니다. “1:then”을 출력합니다.
- 두 번째로
create()
를 호출하여Promise
인스턴스를 생성합니다.executer
블록에서resolve(100)
으로 호출하면,then()
의 첫 번째 파라미터의 핸들러 함수가 실행되며 100이 param에 설정됩니다.return
문의 표현식을 평가한 150을[[PromiseValue]]
에 설정만하고 반환하지 않으며, 실행 중인Promise
인스턴스를 반환합니다.
세 번째로
create()
를 호출하여Promise
인스턴스를 생성합니다.then()
의 첫 번째 파라미터의 핸들러 함수가 호출되면param
파라미터에 100이 설정됩니다.return
문의 표현식을 평가한 170을[[PromiseValue]]
에 설정하고 실행중인Promise
인스턴스를 반환합니다.then()
에서Promise
인스턴스를 반환하므로 두 번째.then()
으로 호출할 수 있습니다.[[PromiseValue]]
에 설정된 170이param
파라미터에 설정되며 “4: then, 170”이 출력됩니다.
코드 실행 순서 정리
- 첫 번째
create()
함수를 호출합니다.Promise
인스턴스를 반환합니다.
연결된then()
의 핸들러 함수를 실행하지 않고 아래로 이동합니다.
- 두 번째
create()
함수를 호출합니다.Promise
인스턴스를 반환합니다.
연결된then()
의 핸들러 함수를 실행하지 않고 아래로 이동합니다.
- 세 번째
create()
함수를 호출합니다.Promise
인스턴스를 반환합니다.
연결된then()
의 핸들러 함수를 실행하지 않고 아래로 이동합니다.
- 더 이상 처리할 코드가 없습니다.
- 첫 번째의
executer
블록의resolve()
가 호출되며then()
의 핸들러 함수가 실행됩니다.
콘솔에 “1:then”이 출력됩니다.
- 두 번째의
executer
블록의resolve()
가 호출되며then()
의 핸들러 함수가 실행됩니다.
콘솔에 “2:then, 100”이 출력됩니다.
- 세 번째의
executer
블록의resolve()
가 호출되며then()
의 핸들러 함수가 실행됩니다.
콘솔에 “3:then, 100”이 출력됩니다.
- 세 번째의
then()
에 연결된then()
의 핸들러 함수가 실행됩니다.
콘솔에 “4:then, 170”이 출력됩니다.
then().then()과 같이 then()이 연결되어 있으면, 처음 then()의 핸들러 함수를 실행한 후, 두 번째 then()의 함수 코드를 실행합니다. 이때 처음 then()의 return 값이 두 번째 then()함수의 파라미터 값으로 설정됩니다.
catch(): 실패 핸들러
실패(reject
) 핸들러를 정의합니다.
Promise.prototype.catch(onRejected)
- 파라미터에
Promise
가reject
상태가 되었을 때 실행될 핸들러 함수를 작성합니다.then()
의 첫 번째 파라미터에 함수를 작성하고, 두 번째 파라미터는 작성하지 않습니다.
대신then().catch()
형태로 작성하여then()
의 두 번째 파라미터에 작성할 함수를 catch()의 파라미터에 작성합니다.then()
은 성공했을 때 실행되며catch()
는 실패했을 때 실행됩니다.
catch()
의 핸들러 함수에 파라미터를 하나만 작성할 수 있습니다.executer
블록의reject()
에서 다수의 파라미터를 넘겨주려면 배열과 같은 형태로 작성해야 합니다.
catch()
의 핸들러 함수에서return
문의 작성 여부와 관계없이 현재 실행 중인Promise
인스턴스를 반환합니다.
catch().then()
과 같이catch()
다음에then()
을 연결할 수 있으며,catch()
에서 설정한[[PromiseValue]]
값을then()
의 파라미터 값으로 넘겨줍니다.
1 | function create(param){ |
- 파라미터로 받은
param
값이“ok”
이면resolve(param)
을 호출하고, 아니면reject(param)
을 호출합니다.“fail”
값으로create()
를 호출합니다. 따라서reject()
를 호출하게 되며,catch()
의 핸들러 함수가 실행됩니다.
create(“fail”)
로 호출하여Promise
인스턴스를 생성합니다.executer
블록에서reject()
가 호출되므로catch()
의 핸들러 함수가 실행됩니다.reject(param)
에서param
값이 핸들러 함수의 파라미터인param
에 설정됩니다.
실패만 발생하므로then()
의 핸들러 함수는 실행되지 않고,catch()
핸들러 함수만 실행됩니다.
1 | function create(param){ |
then()
의 핸들러 함수가 실행되면 콘솔에“1:then, resolve”
가 출력됩니다.
이어서throw
문으로 에러를 발생시킵니다. 그러면then()
에 이어서 작성한catch()
핸들러 함수가 실행됩니다.
executer
블록에서reject()
를 호출해도catch()
의 핸들러 함수가 실행되지만,then()
에서 에러가 발생해도catch()
의 핸들러 함수가 실행됩니다.
이때, 앞then()
의throw
문에 작성한“에러 발생 시킴”
이catch()
핸들러 함수의param
파라미터에 설정됩니다. 콘솔에 “2:catch, 에러 발생 시킴”이 출력됩니다.핸들러 함수에
return
문을 작성하지 않았으므로[[PromiseValue]]
에undefined
가 설정되며 실행 중인Promise
인스턴스가 반환됩니다.catch()
에서 에러가 발생하지 않으면then().catch().then().catch()
형태에서catch()
에 연결된 두 번째then()
이 실행됩니다. 만약 에러가 발생하여 두 번째catch()
를 실행하더라도 소스 코드 전체가 종료되지 않습니다.
then()
이 실행되면catch()
에서[[PromiseValue]]
에 설정한undefined
가param
파라미터에 설정됩니다.콘솔에 “3:then, undefined”가 출력됩니다.
then()
에 이어서catch()
가 있지만,then()
에서 에러가 발생하지 않았으므로catch()
가 실행되지 않습니다.then()
의 핸들러 함수를 실행한 후, 소스 코드 전체가 종료됩니다.
resolve(): 성공 상태의 인스턴스 반환
fulfill
(성공) 상태의 Promise
인스턴스를 반환합니다.
Promise.resolve()
파라미터
value, promise, thenable반환 값
파라미터 값에 따라 반환 형태가 다릅니다.
파라미터에 값을 작성하면 성공 상태의 Promise
인스턴스를 생성하여 반환합니다.
이어서 then()
을 작성하면 then()
의 첫 번째 파라미터에 작성한 함수가 호출됩니다.
파라미터에 Promise
인스턴스를 지정하면 인스턴스를 성공 상태로 변환하여 반환합니다.
1 | 1. let promiseObj = Promise.resolve( |
Promise.resolve()
를 호출하면Promise
인스턴스를 생성하고Promise
를 성공 상태로 설정하여 반환합니다.then()
의 핸들러 함수에 파라미터 하나만 작성할 수 있으므로 다 수의 파라미터 값을 넘겨주기 위해Object
오브젝트로 작성했습니다.- 다음은 promiseObj 인스턴스 구조입니다.
__proto__
에 첨부된 프로퍼티가Promise.prototype
에 연결된 프로퍼티와 같습니다.
이는new
연산자를 사용하지 않고Promise.resolve()
를 실행해도Promise
인스턴스를 생성한다는 의미입니다.[[PromiseState]]
값이“resolve”
로 설정되어 있습니다. 따라서then()
의 첫 번째 파라미터의 핸들러 함수가 실행됩니다.Promise.resolve()
의 파라미터 값이[[PromiseValue]]
에 설정되었으며then()
의 핸들러 함수의 파라미터에 설정됩니다.
PromiseObj
의Promise
인스턴스가 성공 상태이므로then()
의 첫 번째 파라미터 함수가 실행됩니다.이 시점에서 실행되지 않고 소스 코드에 작성된 코드를 끝까지 처리한 후 실행됩니다.
핸들러 함수의param
파라미터에{sports: “스포츠”, music: “음악”}
이 설정됩니다.Promise.resolve()
가Promise
인스턴스를 생성하여 반환하므로then()
을 연결하여 작성할 수 있습니다.
지금then()
의 핸들러 함수를 실행하지 않고, 위에 작성한then()
의 핸들러 함수를 먼저 실행한 후 실행합니다.resolve()
파라미터 값인[“sports”, “music”]
이then()
의 핸들러 함수의param
파라미터에 설정됩니다.
1 | 1. let oneObj = Promise.resolve( |
promise.resolve()
파라미터에promise.resolve()
로 생성한 인스턴스를 지정한 형태입니다.
Promise
인스턴스를 생성하여 반환합니다. 이때resolve( )
의 파라미터 값이[[PromiseValue]]
에 설정됩니다.
Promise.resolve()
파라미터에 앞에서 생성한Promise
인스턴스를 지정했습니다.then()
의 핸들러 함수가 실행되면oneObj
인스턴스[[PromiseValue]]
에 설정된 값이 핸들러 함수의param
파라미터에 설정됩니다. 즉, {sports: “스포츠”}가 설정됩니다.
thenable
let obj = {then(resolve,reject) {…} }
와 같이 오브젝트 안에 then()을 작성한 형태를 thenable이라고 합니다.
1 | 1. let oneObj = Promise.resolve({ |
Promise.resolve()
의 파라미터에Object
오브젝트를 작성하고, 그 안에then()
을 작성했습니다.
이를thenable
이라고 합니다.이 시점에서는Promise
인스턴스만 생성하고then()
을 실행하지 않습니다.소스 코드의 마지막 코드까지 실행한 후
then()
을 실행합니다.oneObj
에 생성한 인스턴스를 할당한 시점의[[PromiseState]]
값은“pending”
입니다.then()
의resolve(“thenable”)
을 호출하기 전까지“pending”
상태 이며 호출하면“resolved”
로 바뀝니다.
oneObj
인스턴스에then()
이 포함되어 있으므로 위 코드를 연결하면oneObj.then().then()
형태가 됩니다.이 형태는 다음과 같은 순서와 방법으로 실행됩니다.
oneObj
인스턴스의then(resolve)
가 실행됩니다.- 콘솔에
“1:then”
을 출력합니다. resolve(“thenable”)
을 호출합니다. 이때[[PromiseValue]]
에“thenable”
을 설정합니다.oneObj.then().then()
형태에서 두 번째then()
이 호출됩니다.- 두 번째
then()
의value
파라미터에[[PromiseValue]]
값인“thenable”
이 설정됩니다. - 콘솔에
“2:thenable”
을 출력합니다.
1 | let thenable = { |
- Object 오브젝트에 then(resolve,reject)를 작성하였으며, resolve() 다음 줄에 reject()를 작성하였습니다. 작성 형태만 보면 resolve()를 호출하고 reject()를 호출할 것으로 보이지만,
성공 또는 실패 하나만 발생하므로 먼저 작성한 resolve()만 호출됩니다.
반대로 reject(), resolve() 순서로 작성하면 reject()만 호출되고 resolve()는 호출되지 않습니다.
Promise.resolve()
파라미터에thenable
오브젝트를 지정하여Promise
인스턴스를 생성합니다. 이때then()
은 실행되지 않습니다.
oneObj.then()
에 두 개의 파라미터를 작성했습니다.
첫 번째 파라미터는resolve()
로 호출했을 때 실행되는 함수이고
두 번째 파라미터는reject()
로 호출했을 때 실행되는 함수입니다.oneObj
인스턴스에then()
이 있으므로oneObj.then()
은then().then()
형태가 됩니다.첫 번째
then()
에서resolve(“resolve”)
를 호출하면[[PromiseValue]]
에“resolve”
가 설정됩니다.
두 번째then()
의 첫 번째 파라미터 함수가 실행되며,value
파라미터에“resolve”
가 설정됩니다.
두 번째 파라미터 함수는reject()
를 호출하였을 때 실행되므로 위 코드에서는 실행되지 않습니다.
reject(): 실패 상태의 인스턴스 반환
reject
(실패) 상태의 Promise
인스턴스를 반환합니다.
Promise.reject()
- 파라미터에 실패 사유를 작성합니다.
- reject 상태로 변환된 Promise 인스턴스를 반환합니다.
1 | 1. let promiseObj = Promise.reject("reject 처리"); |
Promise.reject()
를 실행하면reject
상태의Promise
인스턴스를 생성하여 반환합니다.
파라미터 값이[[PromiseValue]]
에 설정되며,then()
의 두 번째 파라미터 함수의 파라미터 값으로 설정됩니다.다음은 promiseObj 인스턴스 구조입니다.
Promise
인스턴스의 상태는“reject”
입니다. 따라서then()
의 두 번째 파라미터 함수가 호출됩니다.Promise.reject()
파라미터에 작성한“reject 처리”
가[[PromiseValue]]
에 설정됩니다.
promiseObj.then()
에 두 개의 파라미터를 작성했습니다. 첫 번째 파라미터 함수는resolve()
로 호출했을 때 실행되고, 두 번째 파라미터 함수는reject()
로 호출했을 때 실행됩니다.
현재reject
상태이므로 두 번째 파라미터 함수가 실행됩니다.
all(): 모두 성공이면 핸들러 실행
파라미터의 모든 Promise
인스턴스가 성공 상태이면 then()
의 핸들러 함수를 실행합니다.
Promise.all()
- 파라미터에 이터러블 오브젝트를 작성합니다.
이터러블 오브젝트에 작성한 순서로 Promise 인스턴스를 생성합니다.
생성한 모든 Promise 인스턴스가 성공 상태이면, then()의 첫 번째 파라미터 함수를 실행합니다.
Promise 인스턴스가 하나라도 실패한다면, then()의 핸들러 함수를 실행하지 않습니다.
executer
블록에서 resolve()
를 호출한 순서가 아닌 Promise
인스턴스를 생성한 순서로 파라미터 값을 배열에 첨부하여 [[PromiseValue]]
에 설정합니다. then()
의 첫 번째 파라미터 함수에서 파라미터 값으로 사용합니다.
1 | 1. function order(mili) { |
order(mili)
가 호출되면Promise
인스턴스를 생성하면서setTimeout()
을 실행합니다.
파라미터로 받은mili
값을 지연 시간으로 사용합니다. 지연 시간이 경과한 후에setTimeout
의 콜백 함수가 실행됩니다.order()
를 여러 번 호출했을 때, 호출한 순서가 아닌mili
값에 따라 콜백 함수가 실행되므로 실행 순서가 달라질 수 있습니다.
즉, 콜백 함수에서resolve()
호출 순서가 바뀔 수 있습니다.
Promise.all()
의 파라미터에order()
호출을 배열로 작성했습니다.
따라서 첫 번째 엘리먼트부터 차례로order()
함수를 호출하게 됩니다. 호출된order()
함수에서setTimeout()
을 실행하며, 파라미터로 넘겨준 값을 지연 시간으로 사용합니다.
함수 호출에는 시간이 걸리지 않아 (0.1초 안에) 세 개의order() 300,200,100
순서로 호출됩니다.
하지만setTimeout()
의 콜백 함수는 지연 시간으로 인해 100, 200, 300 순서로 실행되게 됩니다.
setTimeout()
에서 지연 시간이 경과하면 콜백 함수에서 resolve(mili)
를 호출하게 되며then()
의 핸들러 함수가 실행됩니다.
이때, Promise.all()
은 resolve(mili)
를 호출할 때 마다 then()
의 핸들러 함수가 실행되지 않습니다.
Promise.all()
의 파라미터에서 order()
호출로 생성한 Promise
인스턴스가 모두 성공적으로 처리되었을 때 한 번만 호출합니다.
Promise.all()
에서 order()
함수를 총 세 번 호출하지만, 생성된 인스턴스가 모두 성공적으로 처리돼야 then()
의 핸들러 함수를 실행하는 것입니다.
실행 결과 “실행 100”, “실행 200”, “실행 300”은 setTimeout
의 콜백 함수가 실행한 출력 값이고,
호출 [300, 200, 100]은 then()
의 핸들러 함수에서 출력한 값입니다.
race(): 처음 한 번만 핸들러 호출
처음 한 번만 then()
의 핸들러 함수를 실행합니다.
Promise.race()
- 파라미터에 이터러블 오브젝트를 작성합니다. 이터러블 오브젝트에 작성한 순서로
Promise
인스턴스를 생성합니다. 처음 한 번만Promise
인스턴스 성공과 실패에 따라then()
의 핸들러 함수를 호출하고, 그 다음 부터는 호출하지 않습니다.
1 | function order(mili) { |
Promise.race()
에서 order(300), order(200), order(100) 순서로 order() 함수를 호출합니다.
하지만Promise.race()
는 처음 한 번만then()
의 핸들러 함수가 실행되므로 order(200), order(100)의 핸들러 함수는 실행되지 않습니다.