프로미스를 사용하면 비동기적으로 수행되는 작업의 성공과 실패를 분리해 그에 맞는 처리를 할 수 있게 된다.
- 프로미스 생성
let promise = new Promise(function(resolve, reject) {
// 실행 코드(성공하면 resolve함수 실행 / 실패하면 reject함수 실행)
});
프로미스 객체는 new Promise()
명령을 통해 생성할 수 있다.
프로미스 생성자의 인자는 반드시 함수(executor)여야하며 이 함수는 프로미스 객체가 생성되면 자동적으로 실행된다.
이 함수의 인자인 resolve, reject함수는 자바스크립트에서 자체적으로 제공된다.
resolve함수는 실행 코드가 성공하면 실행시키는 함수이고 reject함수는 실행코드가 실패했을 때 실행시켜야 하는 함수이다.
resolve함수를 실행할 때 인자로 입력하는 정보는 실행 코드가 성공했을 경우 실행할 함수의 인자로 전달되고,
reject함수를 실핼할 때 인자로 입력하는 정보는 실행 코드가 실패했을 경우 실행할 함수의 인자로 전달된다.
- 프로미스 실행
promise.then(
function () { // 작업 성공시 실행 },
function () { // 작업 실패시 실행 }
);
프로미스 객체의 프로토타입 메서드 then, catch, finally 등으로 프로미스의 콜백함수를 실행한다.
* 함수의 반환값으로 프로미스 객체를 반환하면 원하는 시점에 프로미스 객체를 생성하고 콜백함수도 호출할 수 있다.
function promise() {
return new Promise((resolve, reject) => {
// state : pending
setTimeout(() => {
resolve(); // state : fulfilled
}, 1000);
});
}
promise().then(() => {
console.log('1000ms후에 fulfilled 됩니다.');
})
.catch(e => {
console.log('1000ms후에 rejected 됩니다.', e);
})
.finally(() => {
console.log('end');
});
* setTimeout의 콜백함수를 resolve 또는 reject로 지정하고 thisArg의 값을 지정하면 그 값이 result로 전달된다.
const promise = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
promise.then((values) => {
console.log(values); // 1초 뒤에 "foo" 출력
});
Promise examples )
* producing code(생산 코드) : 코드를 실행하고 그 코드의 실행 성공 여부에 따라 적절한 결과값 전달하는 코드
* consuming code(소비 코드) : 생산 코드의 실행 여부에 따라 그 결과값을 받을 코드
<가수(실행코드)와 그의 팬들(소비코드)>
- 아주 유명한 가수가 있다고 가정해보자. 그의 팬들은 가수의 앨범이 언제 나오는지 궁금해서 그에게 언제 앨범이 발매되는지 계속해서 요청한다.
이 과정은 가수와 팬들 모두에게 비효율적이다. 가수의 입장에서는 앨범이 발매되기 전까지 팬들의 문의에 끊임없이 응답해야 하고 팬들의 입장에서는 계속해서 문의를 하지 않으면 자기도 모르는 사이에 앨범이 발매될 수도 있기 때문에 생각날 때마다 가수에게 앨범에 대한 문의를 해야 하기 때문이다.
이 둘 사이에서 중간 다리 역할을 해주는 것이 바로 Promise이다. 프로미스는 팬들의 이메일 계정을 받아놓고 가수의 앨범이 발매될 때까지 기다렸다가 가수의 앨범이 발매되면 팬들의 이메일 주소로 연락을 해주는 역할을 한다.
즉 프로미스는 가수와 팬들 사이에서 가수의 앨범이 발매되면 팬들에게 알려주기로 약속을 해준다.
// promise producer
const promise = new Promise(function(resolve, reject) {
// 가수가 앨범 작업하는 코드
setTimeout(function() {
if (앨범 발매 성공) {
resolve(3번째_앨범.mp4);
} else {
reject("성대 결절에 걸렸어요ㅠㅡㅠ");
}
}, 3개월);
}
// promise consumer
promise.then(
function(album) {
// 앨범 발매에 성공했을 때 결과를 인자로 받아 실행되는 함수
// 발매된 앨범 = album
},
fucntion(reason) {
// 앨범 발매에 실패했을 때 결과를 인자로 받아 실행되는 함수
// 앨범 발매에 실패한 이유 = reason
}
)
State of promise
프로미스에는 세 가지 상태가 존재한다.
- pending : 대기상태(초기 상태) (settled의 반대)
- fulfilled : 작업이 성공적으로 실행된 상태
- rejected : 작업이 실패한 상태
new Promise로 프로미스 객체를 생성하면 프로미스 객체는 pending 상태가 된다.
객체 내부의 함수(비동기 작업)가 실행되고 resolve 또는 reject 함수가 호출되면 fufill또는 reject상태가 된다.
promise.then( ... )은 또다시 프로미스 객체를 생성한다.
Instanse method
- Promise로 구현된 비동기 함수를 호출하는 측(promise consumer)에서는 Promise 객체의 후속 처리 메소드(then, catch)를 통해 비동기 처리 결과 또는 에러 메시지를 전달받아 처리한다.
.then(onFulfillment, onRejection) : 프로미스가 성공 또는 실패했을 때 실행할 콜백함수(처리기)를 인자로 전달받는다.
프로미스가 성공하면 onFulfillment 실행, 프로미스가 실패하면 onRejection를 실행한다.
호출된 처리기의 반환값으로 새 프로미스를 반환한다. ( => 메소드 체이닝이 가능하다)
만약 onFulfillment 또는 onRejection함수가 처리되지 않은 경우(unfdefined) 원래 처리된 값으로 결정된다.
.catch(onRejection) : 프로미스가 실패했을 때(rejected) 또는 throw Error의 값을 받는다.
- .then(null, onRejection)과 동일하다.
.finally(function) : 프로미스의 성공, 실패와 관계없이 콜백함수가 실행된다.
- .then(function, fucntion)과 동일하다.
Static method
Promise.all(iterable)
iterable 내의 모든 프로미스가 이행한 뒤 이행하고, 어떤 프로미스가 거부하면 즉시 거부하는 프로미스를 반환합니다. 반환된 프로미스가 이행하는 경우 iterable 내의 프로미스가 결정한 값을 모은 배열이 이행 값입니다. 반환된 프로미스가 거부하는 경우 iterable 내의 거부한 프로미스의 이유를 그대로 사용합니다. 이 메서드는 여러 프로미스의 결과를 모을 때 유용합니다.
Promise.race(iterable)
iterable 내의 어떤 프로미스가 이행하거나 거부하는 즉시 스스로 이행하거나 거부하는 프로미스를 반환합니다. 이행 값이나 거부 이유는 원 프로미스의 값이나 이유를 그대로 사용합니다.
Promise.reject()
주어진 이유로 거부하는 Promise 객체를 반환합니다.
Promise.resolve()
주어진 값으로 이행하는 Promise 객체를 반환합니다. 값이 then 가능한 (즉, then 메서드가 있는) 경우, 반환된 프로미스는 then 메서드를 따라가고 마지막 상태를 취합니다. 그렇지 않은 경우 반환된 프로미스는 주어진 값으로 이행합니다. 어떤 값이 프로미스인지 아닌지 알 수 없는 경우, Promise.resolve(value) 후 반환값을 프로미스로 처리할 수 있습니다.
'Programming > JavaScript' 카테고리의 다른 글
Web RTC란? | P2P 연결 과정, NAT, STUN, TURN, ICE (0) | 2021.11.01 |
---|---|
[Javascript] Static Method (0) | 2021.07.03 |
[JavaScript] 객체 내에 존재하는 속성에 접근하기 (0) | 2021.04.19 |
[Javascript] 프로토타입 (1) | 2021.04.12 |
[JavaScript] sort() 메소드를 이용한 배열 정렬 (0) | 2021.04.02 |