
Promise 클래스 자체에 정의된 함수로, Promise 객체를 생성하지 않아도 사용할 수 있는 메서드이다. 여러 개의 프로미스를 동시에 처리하거나, 특정 조건에 따라 프로미스를 다루기 위해 사용된다.
function getName() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("철수");
}, 1000);
});
}
function getTodo() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("밥먹기");
}, 2000);
});
}
getName()
.then((name) => {
console.log(name);
return getTodo();
})
.then((todo) => {
console.log(todo);
});
// (1초 뒤) "철수" (2초 뒤) "밥먹기"
getName()과 getTodo() 비동기 함수를 한번에 하나씩 순차적으로 실행했다. 따라서 총 3초가 걸렸다.

비동기 작업을 순차적으로 한번에 하나씩 수행을 해야할까? getName()과 getTodo() 비동기 함수는 이전 작업에 의존하지 않는 독립적인 비동기 함수이다. 따라서, 굳이 순차적으로 한번에 하나씩 수행하지 않고 동시에 실행해도 된다.

하나의 작업하는데 시간이 오래 걸린다면, 순차적으로 실행하는 방법은 비효율적이다. 병렬적으로 비동기 함수를 동시에 실행한다면 더 빠르게 결과를 얻을 수 있다.
순차적으로 한번에 하나씩 비동기 함수를 호출하는 문제를 해결하기 위해 Promise 객체의 static 함수를 사용한다.
Promise.all(iterable);
Promise.all()은 배열과 같이 순회 가능한 객체로 Promise를 전달받는다. 배열에 값이 들어가도
Promise.resolve() 메서드로 값을 감싸서, 자동으로 Promise로 변환된다.
Promise.all() 메서드는 인자로 받은 Promise 객체들의 상태 변화를 감시하고, 모든 Promise가 성공 되었을 때나 하나라도 실패했을 때 그에 따른 새로운 Promise를 반환한다. 특히, 배열의 요소가 Promise 객체가 아니라 Promise를 반환하는 비동기 함수라면, 모든 비동기 함수가 동시에 실행되어 병렬적으로 작업이 수행된다. 그 후, 비동기 함수가 반환하는 Promise 객체의 상태를 감시한다.
Promise 객체의 static 함수가 인자로 넘어온 비동기 함수를 동시에 실행이 가능한 이유는 자바스크립트 엔진이 비동기 함수를 실행하는 것이 아니기 때문이다. 다시 말해서, 자바스크립트 엔진이 비동기 작업을 실행하는게 아니다. Promise static 함수는 멀티 쓰레드 기반의 Web APIs를 활용하기에 인자로 들어온 비동기 함수를 동시에 실행할 수 있다. 그리고, Web APIs 환경에서 비동기 작업이 완료되면 결과를 자바스크립트 엔진이 받게 된다.
function getName() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("철수");
}, 1000);
});
}
function getTodo() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("밥먹기");
}, 2000);
});
}
const promise = Promise.all([getName(), getTodo()]);
promise.then((data) => {
console.log(data);
});
// ["철수", "밥먹기"]
인자로 전달해준 getName()과 getTodo() 비동기 함수를 동시에 병렬적으로 실행한다. 그 후, 반환된 Promise 객체의 상태를 감시한다. 위 코드에서는 반환된 모든 Promise 객체의 상태가 fulfilled이다. 따라서, Promise.all()이 반환한 Promise의 상태는 fulfilled이며, 결과값은 배열 인자로 넘겨준 모든 Promise 객체의 결과값을 배열로 묶은 것이다.
function getName() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("에러: 이름이 없어요"));
}, 1000);
});
}
function getTodo() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("밥먹기");
}, 2000);
});
}
const promise = Promise.all([getName(), getTodo()]);
promise
.then((data) => {
console.log(data);
})
.catch((error) => {
console.log(error);
});
// Error: 에러: 이름이 없어요
Promise.all() 메서드는 배열 안의 비동기 함수를 동시에 실행한다. 비동기 함수가 rejected 상태의 Promise 객체를 반환하면, 나머지 Promise들이 fulfilled이든 rejected이든지 간에 곧바로 rejected 상태의 새로운 Promise를 반환한다. 이때 새롭게 반환된 Promise 객체의 결과값에는 비동기 작업의 실패 이유(reason)가 들어간다.
Promise.all([]).then(results => {
console.log(results); // []
});
빈 배열을 인자로 전달하면, Promise.all()은 즉시 fulfilled 상태이며 빈 배열을 결과값으로 가지는 Promise를 반환한다.
Promise.allSettled(iterable);
Promise.allSettled()도 배열과 같이 순회 가능한 객체로 Promise를 전달받는다. 마찬가지로 배열에 값이 들어가도 자동으로 Promise로 변환된다.
전달된 모든 Promise들의 상태가 fulfilled이든 rejected이든 간에, 일단 pending을 벗어날 때까지 기다린다.
배열 안의 모든 Promise가 pending 상태를 벗어나면, Promise.allSettled() 메서드는 새로운 Promise 객체를 반환한다. 반환된 Promise 객체는 fulfilled 상태이면서 배열 인자로 넘겨준 Promise 객체를 배열로 묶은 것을 결과값으로 가진다. Promise.allSettled()가 반환하는 Promise는 항상 fulfilled 상태이다.
➡️ 각각의 Promise 객체가 fulfilled 인지 rejected 상태인지 세세하게 알고 싶다면 Promise.all()이 아닌 Promise.allSettled()를 사용해야 한다.
function getName() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("에러: 이름이 없어요"));
}, 1000);
});
}
function getTodo() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("밥먹기");
}, 2000);
});
}
const promise = Promise.allSettled([getName(), getTodo()]);
promise.then((data) => {
console.log(data);
});
Promise.allSettled() 메서드는 getName()과 getTodo() 비동기 함수를 동시에 병렬로 실행시킨다. 그 후, 비동기 함수로부터 반환 받은 모든 Promise 객체의 상태가 pending이 아니라면 Promise.allSettled() 메서드는 새로운 Promise 객체를 반환한다. 해당 Promise 객체는 상태가 fulfilled이며, 배열 인자로 받은 모든 Promise 객체들을 배열로 묶어 결과값으로 가진다. 따라서, 배열 인자로 받은 모든 Promise 객체들의 상태와 결과값을 알 수 있다.


Promise.any(iterable);
Promise.any()도 배열과 같이 순회 가능한 객체로 Promise를 전달받는다. 마찬가지로 배열에 값이 들어가도 자동으로 Promise로 변환된다.
배열 인자로 받은 Promise 객체 중에서 가장 먼저 fulfilled 상태가 된 Promise의 결과값을 Promise.any()가 반환하는 Promise의 결과값이 된다. 그리고, 배열 인자로 받은 모든 Promise의 상태가 rejected일 때만 Promise.any()는 rejected 상태의 Promise를 반환한다.
function getName() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("철수");
}, 1000);
});
}
function getTodo() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("밥먹기");
}, 2000);
});
}
const promise = Promise.any([getName(), getTodo()]);
promise
.then((data) => {
console.log(data);
});
// "철수"
getName() 비동기 함수가 반환하는 Promise 객체가 가장 먼저 fulfilled 상태가 되었기에 data에는 "철수"가 들어갔다.
function getName() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("에러: 이름이 없어요"));
}, 1000);
});
}
function getTodo() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("에러: 할 일이 없어요"));
}, 2000);
});
}
const promise = Promise.any([getName(), getTodo()]);
promise
.then((data) => {
console.log(data);
})
.catch((error) => {
console.log(error);
});


배열 인자로 받은 모든 Promise가 rejected 상태이기에 Promise.any() 메서드가 반환한 Promise 객체도 rejected인 상태이다. 따라서 catch 블럭이 실행되어 error를 출력한다.
Promise.race(iterable);
Promise.race()도 배열과 같이 순회 가능한 객체로 Promise를 전달받는다. 마찬가지로 배열에 값이 들어가도 자동으로 Promise로 변환된다.
배열 인자로 받은 Promise들 중에서 가장 빨리 완료된 Promise의 결과값이 Promise.race()가 반환하는 Promise 객체의 결과값이 된다. 즉, 가장 빨리 pending 상태를 벗어난 Promise의 결과값을 받는다는 것이다.
가장 빨리 완료된 Promise의 상태가 fulfilled이면 Promise.race()가 반환할 Promise의 상태도 fulfilled이며, 가장 빨리 완료된 Promise의 상태가 rejected인 경우 Promise.race()가 반환할 Promise의 상태도 rejected이다.
function getName() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("철수");
}, 1000);
});
}
function getTodo() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("밥먹기");
}, 500);
});
}
const promise = Promise.race([getName(), getTodo()]);
promise
.then((data) => {
console.log(data);
});
// "밥먹기"
getTodo() 메서드가 반환하는 Promise가 제일 먼저 pending 상태에서 벗어난다. 따라서, 반환될 Promise 객체는 가장 먼저 완료된 Promise 객체의 결과를 받아서, fulfilled 상태이면서 "밥먹기"를 결과값으로 가진다.
function getName() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("에러: 이름이 없어요"));
}, 1000);
});
}
function getTodo() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("밥먹기");
}, 2000);
});
}
const promise = Promise.race([getName(), getTodo()]);
promise
.then((data) => {
console.log(data);
})
.catch((error) => {
console.log(error);
})
// Error: 에러: 이름이 없어요
getName() 메서드가 반환하는 Promise가 제일 먼저 pending 상태에서 벗어난다. 따라서, 반환될 Promise 객체는 가장 먼저 완료된 Promise 객체의 결과를 받는다. 즉, Promise.race()가 반환하는 Promise 객체는 rejected 상태이면서 에러 메시지(reason)를 결과값으로 가진다.
Promise.resolve() 메서드는 fulfilled 상태이면서 넘겨준 인자를 결과값으로 하는 Promise 객체를 생성한다.