자바스크립트 12. 프로미스 개념부터 활용까지 JavaScript Promise
위 영상을 기반으로 작성하였음.
2초 후에 'ellie' 가 출력된다.
resolve 를 주석처리하고 reject 를 추가하였더니 2초 후에 Error: no network 가 출력된 것을 확인할 수 있다.
.catch를 추가하여 Error를 다룰 수 있다.
.catch 를 통해 error가 발생했을 때 '🥖'으로 대체하여 cook 까지 도달할 수 있도록 했다.
.catch 부분을 주석처리 했더니 계란 프라이가 되지 못한 채 egg 부분에서 멈춘 것을 확인할 수 있다.
'use strict';
//Promise is a JavaScript object for asynchronous operation.
// State: pending -> fulfilled or rejected
// Producer 와 Consumer
// 1. Producer
// when new Promise is created, the executor runs automatically.
const promise = new Promise((resolve, reject) => {
//doing some heavy work (network, read files)
console.log('doing something...');
setTimeout(() => {
resolve('ellie');
//reject(new Error('no network'));
}, 2000);
});
//2. Consumers: then, catch, finally
promise.then((value) => {
console.log(value);
})
.catch(error => {
console.log(error);
})
.finally(() => {
console.log('finally');
})
//성공과 실패에 상관없이 어떤 기능을 마지막으로 수행하고 싶을 때 사용할 수 있음.
아래는 지난 번에 만들었던 콜백지옥이다. promise를 통해 이 콜백지옥을 수정해보자.
// Callback Hell example
class UserStorage {
loginUser(id, password, onSuccess, onError) {
setTimeout(() => {
if (
(id === 'ellie' && password === 'dream') || (id === 'coder' && password === 'academy')
) {
onSuccess(id);
} else {
onError (new Error('not found'));
}
}, 2000);
}
getRoles(user, onSuccess, onError) {
setTimeout(() => {
if (user === 'ellie') {
onSuccess({ name: 'ellie', role: 'admin'});
} else {
onError(new Error('no access'));
}
}, 1000);
}
}
const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');
userStorage.loginUser(
id,
password,
user => {
userStorage.getRoles(
user,
userWithRole => {
alert(
`Hello ${userWithRole.name}, you have a ${userWithRole.role} role`
);
},
error => {
console.log(error);
}
);
},
error => {
console.log(error);
})
아래 코드로 수정이 되었따.
// Callback Hell example
class UserStorage {
loginUser(id, password) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (
(id === 'ellie' && password === 'dream') ||
(id === 'coder' && password === 'academy')
) {
resolve(id);
} else {
reject(new Error('not found'));
}
}, 2000);
});
}
getRoles(user) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (user === 'ellie') {
resolve({ name: 'ellie', role: 'admin' });
} else {
reject(new Error('no access'));
}
}, 1000);
});
}
}
const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');
userStorage.loginUser(id, password)
.then(user => userStorage.getRoles)
// .then(userStorage.getRoles)로 생략가능
.then(user => alert(`Hello ${user.name},
you have a ${user.role} role`))
.catch(console.log);
프로미스 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과값을 나타냄.
프로미스를 사용하면 비동기 메소드를 동기 메소드처럼 값을 반환할 수 있다.
다만, 최종 결과를 반환하지는 않고 프로미스를 반환해서 미래의 어떤 시점에 결과를 제공한다.
프로미스가 가지는 상태들
1. 대기 (pending): 이행하거나 거부되지 않은 초기상태.
2. 이행 (fulfilled): 연산이 성공적으로 완료.
3. 거부 (rejected): 연산이 실패.
대기 중인 프로미스는 값과 함께 이행될수도, 어떤 오류로 인해 거부될 수도 있다.
이행이나 거부일 때, 프로미스에 연결한 처리기는 그 프로미스의 then 메소드에 의해 대기열에 오른다.
- 대기 (pending)
new Promise();
new Promise(function(resolve, reject) {
// ...
});
new Promise()
메소드를 호출할 때, 콜백함수를 선언할 수 있고 콜백함수의 인자는 resolve, reject 이다.
- 이행 (fulfilled)
new Promise(function(resolve, reject) {
resolve();
});
콜백 함수의 인자 resolve를 실행하면 이행 상태가 된다.
function getData() {
return new Promise(function(resolve, reject) {
var data = 100;
resolve(data);
});
}
// resolve()의 결과 값 data를 resolveData로 받음
getData().then(function(resolvedData) {
console.log(resolvedData); //100
});
이행 상태가 되려면 위 코드와 같이 then()
을 이용하여 처리 결과값을 받을 수 있다.
- 거부 (rejected)
new Promise(function(resolve, reject) {
reject();
});
reject를 호출하면 실패 상태가 됨.
function getData() {
return new Promise(function(resolve, reject) {
reject(new Error("Request is failed"));
});
}
// reject() 의 결과 값 Error를 err에 받음
getData().then.catch(function(err) {
console.log(err); //Error: Request is failed
});
실패 상태가 되면 실패한 이유 (실패 처리의 결과 값)를 catch()
로 받을 수 있다.
프로미스의 메소드들
1. promise.prototype.catch()
프로미스에 거부 처리기 콜백을 추가하고 호출된 경우 콜백의 반환값 또는 프로미스가 대신 이행된 경우 그 원래 이행(fulfillment)값으로 결정하는(resolving) 새 프로미스를 반환.
2. promise.prototype.then()
프로미스에 이행 또는 거부 처리기를 추가하고 호출된 처리기의 반환값 또는 프로미스가 처리되지 않은 경우 그 원래 처리된(settled) 값으로 결정하는 새 프로미스를 반환.
3. promise.prototype.finally()