비동기를 간편하게 처리할 수 있도록 도와주는 오브젝트이다.
프로미스는 자바스크립트 안에 내장되어 있는 오브젝트이며, 비동기적인 것을 수행할 때 콜백함수 대신 유용하게 사용할 수 있는 오브젝트이다.
정해진 장시간의 기능을 수행한 뒤, 정상적으로 기능이 수행되었다면 성공메세지와 함께 처리된 결과값을 전달하고, 기능을 수행하다가 문제가 발생한다면 에러를 전달해준다.
네트워크통신이나 파일을 읽어 오는 것 등 어떤 무거운 일을 처리할 때 사용 될 수 있다.
→ 네트워크에서 데이터를 받아오거나 파일에서 큰 데이터를 읽어오는 과정은 다소 시간이 소요된다. 이를 만약 동기적으로 수행한다면 다음 라인의 코드가 실행되지 않기 때문에, 프로미스를 통해 비동기적으로 처리하는 것이 좋다.
(1) state(상태)
프로세스가 무거운 작업을 수행하고 있는 중인지, 혹은 기능 수행을 완료(성공or실패) 했는지에 대한 상태(state)를 이해한다.
pending
: 대기 상태로서 아직 resolve 할지 reject 할 지 결정되지 않은 초기의 상태이다.fulfilled
: 이행 상태로써 연산이 성공적으로 완료된 상태이다.rejected state
: 거부 상태로써 (파일을 찾을 수 없거나 네트워크에 문제가 생긴 이유 등) 실패된 상태이다.✍️ pending 상태 예시 ▼
function fetchUser() {
return new Promise((resolve, reject) => {
return ('seul');
})
}
const user = fetchUser();
console.log(user);
//resolve나 reject를 호출하지 않았기 때문
✍️ fulfilled 상태 예시 ▼
function fetchUser() {
return new Promise((resolve, reject) => {
resolve('seul');
})
}
const user = fetchUser();
console.log(user);
(2) producer & consumer
producer와 consumer의 차이에 대해 이해한다.
producer
: 원하는 데이터를 제공한다.
consumer
: 제공된 데이터를 필요로 한다. 즉 데이터를 소비하는 측이다.
then()
// ex.1) resolve와 then
const promise = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve("resolve");
}, 3000);
});
promise.then(value => console.log(value));
// 3초 후에 결과가 출력
// resolve
// ex.2) reject와 then
const promise = new Promise((resolve, reject)=>{
setTimeout(()=>{
reject("reject");
}, 3000);
});
promise.then(value => console.log(value));
// UnhandledPromiseRejectionWarning: reject
catch()
ex.2)
의 경우, catch를 사용해서 에러를 잡아줄 수 있다.ex.3)
catch가 then 뒤에 연결되어 있다고 해서 then이 실행된 후 catch가 실행되는 것은 아니다.// ex.3) reject와 catch
const promise = new Promise((resolve, reject)=>{
setTimeout(()=>{
reject("reject");
}, 3000);
});
promise.then(result => console.log(result)).catch(error => console.log(error));
// 3초 후에 결과가 출력
// reject
then() & catch()
then
과 catch
메서드는 프로미스를 반환하기 때문에, 체이닝이 가능하다.finally()
new
라는 키워드를 이용해서 오브젝트를 생성할 수 있다. executor
라는 콜백함수를 전달해 주어야 한다. 이 콜백함수에는 또 다른 두가지 콜백함수를 받는다. ▼✍️ 예제를 작성해보자.
const promise = new Promise((resolve, reject) => {
console.log('doing something...'); // 즉시 실행된다.
});
// result ▼
// doing something
▲ ❗️ new Promise
가 만들어 질 때는, 전달한 executor
라는 콜백 함수가 즉시 실행된다.
console.log
가 즉시 실행된다는 것은 프로미스를 만드는 순간 전달한 executor라는 콜백함수가 바로 실행된다는 의미이다. (1) resolve & reject
// Producer
const promise = new Promise((resolve, reject) => {
console.log('doing something...');
setTimeout(() => {
resolve('seul');
}, 2000)
});
// Consumers
promise.then((value) => {
console.log(value);
});
// result ▼
// 'doing something...'
// (2초뒤) seul
▲ then
은 프로미스가 정상적으로 수행되어서 resolve
라는 콜백함수를 통해서 전달한 값이 value
의 파라미터로 전달되어 들어온 것이다.
(2) resolve & reject
// Producer
const promise = new Promise((resolve, reject) => {
console.log('doing something...');
setTimeout(() => {
// resolve('seul');
reject(new Error('이유를 잘 명시한다. ex) no network'))
}, 2000)
});
// Consumers
promise
.then((value) => {
console.log(value);
})
.catch((error) => {
console.log(error);
})
.finally(()=> {console.log('finally')})
;
// result ▼
// 'doing something...'
// (2초뒤) Error: 이유를 잘 명시한다. ex) no network
// finally
▲ 보통 에러라는 오브젝트를 통해서 값을 전달한다. Error
라는 클래스는 자바스크립트에서 제공하는 오브젝트중 하나이다. MDN-Error생성자
then
, catch
, finally
를 이용해서 값을 받아온다.value
파라미터는 프로미스가 잘 수행 되어서 마지막으로 전달된 값이 들어온다.// 서버에서 숫자를 받아오는 프로미스
const fetchNumber = new Promise((resolve, reject) => {
setTimeout(()=> resolve(1), 1000); // 1초후에 숫자 1 을전달
});
fetchNumber
.then(num => num*2)
.then(num => num*3)
.then(num => {
return new Promise((resolve, reject) => {
setTimeout(()=> resolve(num-1), 1000);
})
})
.then(num => console.log(num));
// result ▼
// (2초뒤) 5
then
은 값을 바로 전달할 수도 있고, Promise
를 전달해도 된다. 이처럼 then
을 여러번 묶어서 처리할 수도 있다.promise.then
을 호출하면 프로미스가 반환되기 때문이며, 반환된 프로미스엔 당연히 .then
을 호출할 수 있다.(1) 프로미스 체이닝
const getHen = () =>
new Promise((resolve, reject) => {
setTimeout(() => resolve('🐓'), 1000);
});
const getEgg = hen =>
new Promise((resolve, reject) =>{
setTimeout(() => resolve(`${hen} => 🥚`), 1000);
});
const cook = egg =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${egg} => 🍳`), 1000);
});
getHen()
.then(hen => getEgg(hen))
.then(egg => cook(egg))
.then(meal => console.log(meal));
// result ▼
// 🐓 => 🥚 => 🍳
getHen().then(getEgg).then(cook).then(console.log);
(2) 에러 핸들링
const getHen = () =>
new Promise((resolve, reject) => {
setTimeout(() => resolve('🐓'), 1000);
});
const getEgg = hen =>
new Promise((resolve, reject) =>{
setTimeout(() => reject(new Error(`${hen} => 🥚`)), 1000);
});
const cook = egg =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${egg} => 🍳`), 1000);
});
getHen()
.then(getEgg)
// 이부분에서 발생하는 에러를 처리하고 싶다면
// 바로 뒤에 catch를 작성해서 바로바로 문제를 해결할 수 있다.
.catch(error => {
return '🧀';
})
.then(cook)
.then(console.log)
.catch(console.log);
// result ▼
// 🧀 => 🍳
catch
는 도중에 에러가 발생했고, 에러처리가 안된 상황이라면, 해당 에러가 전달되어서 마지막에 호출된다.catch
를 작성해서 문제해결을 바로 한 것이다.🙂)✍️ 궁금했던 것
❓then
은 성공했을 경우에만 실행되는 것 같은데, 그럼 왜 인수를 두 가지로 받는다는 설명이 있을까?🤔
then()
메소드는 두개의 콜백 함수의 인수를 받고 이행 및 거부 여부에 따라서 다르게 실행된다.then()
문법 ▼ promise.then(
function(result) { /* 결과(result)를 다룬다 */ },
function(error) { /* 에러(error)를 다룬다 */ }
);
let promise = new Promise(function(resolve, reject) {
setTimeout(() => resolve("done!"), 1000);
});
// resolve 함수는 .then의 첫 번째 함수(인수)를 실행한다.
promise.then(
result => alert(result), // 1초 후 "done!"을 출력한다.
error => alert(error) // 실행되지 않는다.
);
let promise = new Promise(function(resolve, reject) {
setTimeout(() => reject(new Error("에러 발생!")), 1000);
});
// reject 함수는 .then의 두 번째 함수를 실행한다.
promise.then(
result => alert(result), // 실행되지 않는다.
error => alert(error) // 1초 후 "Error: 에러 발생!"를 출력한다.
);
❓ 그러면 catch
와는 어떻게 다를까?
catch(errorHandlingFunction)
를 써도 된다. catch
는 then
에 null
을 전달하는 것과 동일하게 작동한다.then
으로 에러가 발생한 경우만 다루고 싶다면 then(null, errorHandlingFunction)
같이 null
을 첫 번째 인수로 전달하면 된다.let promise = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error("에러 발생!")), 1000);
});
// .catch(f)는 promise.then(null, f)과 동일하게 작동한다.
promise.catch(alert); // 1초 뒤 "Error: 에러 발생!"을 출력한다.
✍️ 작업이 성공적으로 처리된 경우만 다루고 싶다면 then
에 인수를 하나만 전달하면 된다. 🙂
✍️ .catch(f)
는 문법이 간결하다는 점만 빼고 .then(null,f)
과 같다.
reference
MDN-Error생성자
MDN-then
MDN-catch
MDN-promise
dream coding
promise
js-promise