- 자바스크립트에서 비동기 처리를 위해 콜백 함수를 사용하였다. 하지만 콜백 함수를 반복해서 사용하면 콜백 지옥이 발생하는 문제점이 있었고 이를 해결하기 위해 Promise를 사용하는 방법이 있다. Promise는 자바스크립트 비동기 처리에 사용되는 객체이다.
- Promise를 사용하면 비동기 처리 시점을 명확하게 표현할수 있고 연속된 비동기 처리 작업을 쉽게 확인할 수 있으며 추가, 수정, 삭제 작업을 유연하게 처리할 수 있다.
let promise = new Promise((resolve, reject) => {
// 정상적으로 처리되는 경우, resolve의 인자에 값을 전달할 수도 있다.
resolve(value);
// 에러가 발생하는 경우, reject의 인자에 에러 메세지를 전달할 수도 있다.
reject(error);
});
프로미스의 상태란 프로미스의 처리 과정을 의미하며 프로미스를 생성하고 종료될 때까지 3가지 상태를 갖는다.
new Promise((resolve, reject) => {
...
});
new Promise((resolve, reject) => {
resolve("success");
});
new Promise((resolve, reject) => {
reject("failure");
});
new Promise가 반환하는 Promise 객체는 state, result 내부 프로퍼티를 갖는다. 하지만 직접 접근할 수 없고 .then, .catch, .finally 메서드를 사용해야 접근이 가능하다.
State - 기본 상태는 pending(대기) 이며 비동기 처리를 수행할 콜백 함수(executor)가 성공적으로 작동했다면 fulfilled(이행)로 변경이 되고 에러가 발생했다면 rejected(거부)가 된다.
Result - 초기값은 undefined 이며 비동기 처리를 수행할 콜백 함수(executor)가 성공적으로 작동하여 resolve(value)가 호출되면 value로, 에러가 발생하여 reject(error)가 호출되면 error로 변한다.
let promise = new Promise((resolve, reject) => {
resolve("success");
});
promise.then(value => {
console.log(value); // "success"
})
let promise = new Promise(function(resolve, reject) {
reject(new Error("error!"))
});
promise.catch(error => {
console.log(error); // Error: error!
})
let promise = new Promise(function(resolve, reject) {
resolve("success");
});
promise
.then(value => {
console.log(value); // "success"
})
.catch(error => {
console.log(error);
})
.finally(() => {
console.log("성공이든 실패든 작동"); // "성공이든 실패든 작동"
})
let promise = new Promise(function(resolve, reject) {
resolve('success');
...
});
promise
.then((value) => {
console.log(value);
return 'success';
})
.then((value) => {
console.log(value);
return 'success';
})
.then((value) => {
console.log(value);
return 'success';
})
.catch((error) => {
console.log(error);
return 'failure';
})
.finally(() => {
console.log('성공이든 실패든 작동!');
});
const promiseOne = () => new Promise((resolve, reject) => setTimeout(() => resolve('1초'), 1000));
const promiseTwo = () => new Promise((resolve, reject) => setTimeout(() => resolve('2초'), 2000));
const promiseThree = () => new Promise((resolve, reject) => setTimeout(() => resolve('3초'), 3000));
// 기존
const result = [];
promiseOne()
.then(value => {
result.push(value);
return promiseTwo();
})
.then(value => {
result.push(value);
return promiseThree();
})
.then(value => {
result.push(value);
console.log(result); // ['1초', '2초', '3초']
})
// promise.all
Promise.all([promiseOne(), promiseTwo(), promiseThree()])
.then((value) => console.log(value)) // ['1초', '2초', '3초']
.catch((err) => console.log(err));
Promise.all()은 여러 개의 비동기 작업을 동시에 처리하고자 할때 사용한다. 배열을 인자로 받고 해당 배열에 있는 모든 Promise에서 executor 내 작성했던 코드들이 정상적으로 처리가 되었다면 결과를 배열에 저장해 새로운 Promise를 반환 한다.
Promise chaining을 사용했을 경우는 코드들이 순차적으로 동작되기 때문에 위의 예시에서 총 6초의 시간이 걸리고 같은 코드가 중복되는 현상도 발생하게 된다.
Promise.all()을 통해 이러한 문제들을 해결할 수 있으며 비동기 작업들을 동시에 해결하기 때문에 총 3초의 시간이 걸린다. 또한 Promise chaining으로 작성한 코드보다 간결해진다.
Promise.all([
new Promise((resolve, reject) => setTimeout(() => reject(new Error('error1'))), 1000),
new Promise((resolve, reject) => setTimeout(() => reject(new Error('error2'))), 2000),
new Promise((resolve, reject) => setTimeout(() => reject(new Error('error3'))), 3000),
])
.then((value) => console.log(value))
.catch((err) => console.log(err)); // Error: error1
