이전 글
[자바스크립트] 프로미스 객체
이전 글 [자바스크립트] 비동기로 데이터 가져오기, 콜백 헬 이전 포스팅 [자바스크립트] 비동기 작업, 이벤트 루프와 태스크 큐 이전 글 [자바스크립트] 동기와 비동기 동기와 비동기 동기 Synchro
gobae.tistory.com
프로미스의 정적 메서드 알아보기
앞선 포스팅에서는, 프로미스 객체 프로토타입 메서드인 then, catch, finally에 대해 살펴봤다.
이번에는 프로미스의 5가지 정적 메서드를 예시와 함께 알아보자.
프로미스의 정적 메서드는 5가지가 있다.
- resolve
- reject
- all
- race
- allSettled
resolve, reject 메서드는 이전 포스팅에서 콜백에 넣어뒀던 인자와 유사하다.
const pr = Promise.resolve("Tom");
pr.then(data => console.log(data)) // "Tom"
// 위의 코드와 아래의 코드는 동일하기 동작한다.
const pr2 = new Promise((resolve, reject)=>resolve("Tom"));
pr2.then(data => console.log(data)) // "Tom"
reject도 똑같이 사용할 수 있다.
Promise.all
앞으로 살펴볼 all, race, allSettled 메서드는
모두 여러개의 비동기 작업을 병렬 처리할 때 사용한다.
먼저 Promise.all
const get = (url) => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.send();
xhr.onload = () => {
if (xhr.status === 200) {
resolve(JSON.parse(xhr.response));
} else {
reject("Error!");
}
};
});
};
const url = "https://jsonplaceholder.typicode.com";
const pr1 = get(`${url}/posts/1`);
const pr2 = get(`${url}/posts/2`);
const pr3 = get(`${url}/posts/3`);
pr1.then((data) => console.log(data));
pr2.then((data) => console.log(data));
pr3.then((data) => console.log(data));
3가지 비동기 작업 pr1,pr2,pr3이 있다.
이 작업들은 비동기이므로, 실행 순서가 보장되지 않는다.
실행순서 1,2,3과는 달리 3,1,2 순으로 완료되었다.
그런데 만약 1,2,3의 비동기 작업이 모두 완료된 이후에!
다른 A라는 작업을 수행해야 한다면??
현재로서는 1,2,3의 작업 중 어떤 작업이 가장 나중에 끝날 지 예측할 수 없다.
이 때 Promise.all을 사용해서 병렬처리를 하고, 3가지 비동기 작업이 모두 끝난 후 A작업을 수행할 수 있다.
all 메서드의 인수로는 프로미스 객체를 담은 배열을 전달해주고, then을 통해서 처리해줄 수 있다.
const get = (url) => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.send();
xhr.onload = () => {
if (xhr.status === 200) {
resolve(JSON.parse(xhr.response));
} else {
reject("Error!");
}
};
});
};
const url = "https://jsonplaceholder.typicode.com";
const pr1 = get(`${url}/posts/1`);
const pr2 = get(`${url}/posts/2`);
const pr3 = get(`${url}/posts/3`);
Promise.all([pr1, pr2, pr3]).then((data) => console.log(data));
console.log("End");
all 메서드를 통해 pr1,pr2,pr3가 끝난 resolve 값들의 배열을 전달 받아서
then 메서드에서 A작업을 수행할 수 있게 되었다.
또한 pr1의 결과는 배열 0번째, pr2의 결과는 1번에 담기므로,
각각의 비동기 작업이 언제 끝났는지에 관계 없이 결과의 순서가 유지된다.
다만, Promise.all은 모든 프로미스가 Resolve 되어야 한다.
배열의 프로미스 중 하나라도 Reject 된다면 즉시 종료되며,
이 에러 처리를 then.catch를 통해 처리해줘야 한다.
Promise.race
Promise끼리 레이스를 펼친다.
all 메서드처럼 프로미스를 담은 배열을 전달받는다.
전달받은 프로미스 중에 가장 먼저 끝난 프로미스의 결과만을 반환한다.
(= 주의. 가장 먼저 pending을 탈출한 결과만을 반환하므로 fullfilled / rejected 둘 다 가능하다.)
race 역시 프로미스가 reject 된다면, catch를 통해 처리해줘야 한다.
race 적용 예를 생각해보자.
특정 작업을 수행하는 방법이 A,B,C가 있다.
그러나, 어떤 작업이 가장 빨리 끝나는지 알 수 없다.
이때는 어떤 작업이던지 먼저 끝나기만 하면 된다.
하나라도 작업이 완료되었다면 다른 작업이 끝날 때 까지 기다릴 필요가 없다.
여기서 완료는 fullfilled이거나 rejected임을 의미한다.
이 상황에서는 race 메서드로 가장 빠른 결과를 가져올 수 있겠다.
사용 방법은 all과 동일하다.
Promise.race([Promise객체, Promise객체, Promise객체])
.then(data=>console.log(data));
Promise.allSettled
settled이란, 프로미스의 상태가 결정된 것을 의미한다.
즉, fullfilled 되었거나 rejected 된 모든 상태 = settled 되었다 라고 이해한다.
그렇다면, allSettled는 배열로 전달받은 프로미스들의 상태가 모두 결정되었음을 의미한다.
모든 상태가 결정되었다면, then을 이용해서 다음 작업을 진행할 수 있다!
all은 reject가 하나라도 결정되면, 작업을 중지하므로 allSettled가 출현했다.
allSettled이 all, race와 다른 점?
then에서 받은 배열을 보면, 각 인덱스에 promise 처리 결과 객체가 담겨있다.
allSettled의 결과를 출력해보면
이처럼 {status:"", value:""} 의 형태를 가진다.
왜 allSettled는 다르게 출력될까?
all, race의 then에서는 항상 fullfilled된 프로미스만 있다.
그러나, allSettled에서는 fullfilled, rejected 모두 가질 수 있다.
status 속성을 통해 rejected임을 알려줘야, 개발자가 rejected 프로미스에 대한 후속처리를 할 수 있기 때문이다.
현재 아직 해결하지 못한 문제는...
Promise 객체의 비동기 작업이 완료되기 전에 console.log("End")가 먼저 실행되던 문제다.
다음 마지막 비동기는 async/await이다.
이것을 이용하면, 비동기 작업을 동기적으로 기다려줄 함수를 작성할 수 있다.
그 전에 마이크로 태스크큐에 대해서 먼저 알아보자.
다음 글
[자바스크립트] 마이크로 태스크 큐
이전 글 [자바스크립트] 프로미스를 이용한 비동기 작업 병렬 처리 이전 글 [자바스크립트] 프로미스 객체 이전 글 [자바스크립트] 비동기로 데이터 가져오기, 콜백 헬 이전 포스팅 [자바스크립
gobae.tistory.com
'JavaScript > theory' 카테고리의 다른 글
[자바스크립트] 비동기 작업의 동기 처리를 위한 Async/Await (0) | 2021.08.22 |
---|---|
[자바스크립트] 마이크로 태스크 큐와 프로미스 (0) | 2021.08.22 |
[자바스크립트] 프로미스 객체 (0) | 2021.08.22 |
[자바스크립트] 비동기로 데이터 가져오기, 콜백 헬 (0) | 2021.08.22 |
[자바스크립트] 비동기 작업, 이벤트 루프와 태스크 큐 (1) | 2021.08.22 |