JS

<JAVA Script> Promise 의 동시성

제이미로그 2024. 5. 28. 18:01

📌 1. Promise 와 유사한 객체 Thenables 인터페이스

 

thenable은 두 개의 콜백(하나는 프로미스가 이행될 때, 다른 하나는 거부될 때)과 함께 호출되는 .then() 메서드를 구현한다. 프로미스 또한 thenable이다.  이를 통해 기존 객체에 then 메서드를 추가하여 프로미스와 호환되게 만들 수 있다. Thenable 객체는 특히 라이브러리나 프레임워크에서 비동기 작업을 표준화된 방식으로 처리할 때 유용하다. 

 

* Thenable 과 Promise 의 차이점

Promise는 ECMAScript 2015(ES6) 표준에서 정의된 내장 객체이다.  Promise는 비동기 작업의 결과를 나타내며, 세 가지 상태(대기, 이행, 거부)를 가진다. 반면에, Thenable은 then 메서드를 구현한 임의의 객체이다. Thenable은 특정 표준을 따르지 않지만, then 메서드를 통해 Promise와 유사한 방식으로 동작한다. 

 

 

📌 2. Promise 의 동시성

 

Promise 클래스는 비동기 작업 동시성을 용이하게 하기 위해 네 가지 정적 메서드를 제공한다.

 

1. Promise. all() : 주어진 모든 프로미스가 이행되거나 하나라도 거부될 때까지 대기하는 프로미스를 반환한다. 이는 병렬과 비동기 작업을 수행하고 모든 작업이 완료된 후에 그 결과를 한 번에 처리하고자 유용하다. 모든 프로미스가 이행되면 이행되고, 프로미스 중 하나라도 거부되면 거부된다. 

 

작동방식 : 1. 입력: 이터러블(보통 배열) 형태로 프로미스들을 받는다. / 반환값: 새로운 프로미스가 반환된다.

                    2. 모든 입력 프로미스가 이행되면, 반환된 프로미스는 이행된다. 이때 각 프로미스의 결과가 배열로 전달된다

                    3. 입력 프로미스 중 하나라도 거부되면, 반환된 프로미스는 첫 번째 거부된 프로미스의 이유를 사용하여 거부된다.

 

<예제 1>

 

이 코드는 세 개의 프로미스를 생성하고, Promise.all() 메서드를 사용하여 모든 프로미스가 이행될 때까지 기다린 후 그 결과를 출력한다.

 

1. promise1: Promise.resolve(3)를 사용하여 값이 3인 프로미스를 생성한다.

2. promise2: 값이 42인 변수로 프로미스가 아니므로 그대로 배열에 포함된다. 

3. promise3: 0.1초 후에 값이 'foo'인 프로미스를 생성한다. 

4. Promise.all(): 세 개의 프로미스를 포함하는 배열을 받아 모든 프로미스가 이행될 때까지 기다린 후 그 결과를 반환하는 새로운 프로미스를 생성한다. 

5. then(): 모든 프로미스가 이행될 때 호출된다. 그 때 이행된 값들을 배열로 받아와서 출력한다. 

 

=> 결과값 > Array [3, 42, "foo"]

 

 

2. Promise. allSettled() : 여러 개의 비동기 작업을 처리할 때 사용되고 각 작업의 성공 여부와 관계없이 모든 작업의 결과를 알고자 할 때 매우 유용하다. 이 메서드는 주어진 모든 프로미스가 완료(성공 또는 실패)될 때까지 기다렸다가 각 프로미스의 결과를 나타내는 객체 배열을 반환한다. 이를 통해 모든 프로미스의 상태와 결과를 확인할 수 있다. 모든 프로미스가 해결되면 이행된다. 

 

* 구문

iterable : 프로미스들의 배열(또는 반복 가능한 개체)

 

* 반환값

모든 프로미스가 완료된 후, 각 프로미스의 결과를 나타내는 객체 배열을 반환하는 프로미스를 반환한다. 각 객체는 다음과 같은 속성을 가진다.

- status: "fulfilled"(성공) 또는 "rejected"(실패).

- value: status가 "fulfilled"인 경우, 프로미스의 결과값.

- reason: status가 "rejected"인 경우, 프로미스가 실패한 이유.

 

<예제 2>

 

 

이 코드는 모든 프로미스가 완료될 때까지 기다렸다가, 각 프로미스의 결과를 나타내는 객체 배열을 반환한다. 이 예제에서는 두 개의 프로미스가 있다:

하나는 즉시 성공하고, 다른 하나는 100밀리초 후에 실패한다.

 

1. const promise1 = Promise.resolve(3); : promise 1은 즉시 성공하는 프로미스로 결과값은 3이다.

2. const promise2 = new Promise((resolve, reject) = > setTimeout(reject, 100, 'foo) 

: promise2는 100밀리초 후에 실패하는 프로미스로 실패 이유는 'foo'이다.

3. const promises = [promise1, promise 2];

    Promise.allSettled(promises).then((results) =>

    results.forEach((result)) => console.log(result.status)),);  : promise.allSettled는 프로미스 배열의 모든 프로미스가 완료될 때까지 대기.

   results는 각 프로미스의 결과를 나타내는 객체들의 배열이다. 각 객체는 status 속성을 가지고 있으며, 이는 프로미스가 성공했는 지 실패 했는 지를

   나타낸다. 

4. result.forEach((result) => console.log(result.status)); : 각 결과 객체의 status 를 콘솔에 출력한다. 

 

=> 결과값 > "fulfilled"     (즉시 성공하므로 status는 fulfilled)

                 > "rejected"    (100밀리초 후에 실패하므로 status는 rejected)

 

 

3. Promise. any() : 주어진 프로미스들 중에서 하나라도 이행되었을 때, 해당 프로미스의 결과를 반환하는 메서드이다. 모든 프로미스가 거부되었을 때만 거부되는 프로미스를 반환한다. 이는 Promise.all()이나 Promise.race()와는 다른 동작 방식으로, 특히 여러 비동기 작업 중 하나라도 성공하면 되는 경우 유용하다. 

 

<예제 3>

 

Promise.any()를 사용하여 여러 프로미스 중 하나라도 이행되는 첫 번째 프로미스를 처리한다. 이 코드에서, promise1은 즉시 거부되고, promise2는 100ms 후에 이행되며, promise3는 500ms 후에 이행된다. Promise.any()는 첫 번째로 이행되는 프로미스를 반환하기 때문에, 이 경우 promise2의 값인 'quick'이 콘솔에 출력된다.

 

1. promise1 : 즉시 거부됨(Promise.reject(0)).

2. promise2 : 100ms 후에 'quick' 값으로 이행됨.

3. promise3 : 500ms 후에 'slow' 값으로 이행됨.

4. promise.any(promises) : 전달된 프로미스 배열 중에서 가장 빨리 이행된 프로미스의 값을 반환한다. 이 경우, promise2가 100ms 후에 'quick' 값으로 가장 빨리 이행되므로, 'quick'이 출력된다. 

 

실행 결과 : 이 코드를 실행하면 콘솔에 quick이 출력된다. promise2가 100ms 후에 가장 먼저 이행되기 때문이다.

 

=> 결과값 > "quick"  

 

 

4. Promise. race() : 주어진 프로미스 중 가장 먼저 이행되거나 거부된 프로미스 객체를 반환한다. 즉, 첫 번째로 완료된 프로미스의 결과나 오류를 반환한다. 이는 경쟁 상황에서 가장 빨리 완료된 작업의 결과를 얻고자 할 때 유용하다. 프로미스 중 하나라도 해결되면 해결된다. 즉, 프로미스 중 하나라도 이행되면 이행되고, 약속 중 하나라도 거부되면 거부된다. 

 

<예제 4>

 

Promise.race()를 사용하여 두 개의 프로미스 중에서 가장 먼저 이행된 프로미스의 결과를 출력하는 예제이다.  promise1은 500ms 후에 이행되고, promise2는 100ms 후에 이행된다. 따라서 promise2가 더 빠르게 이행되므로 Promise.race()promise2의 결과를 반환한다. 

 

실행 결과 : 이 코드를 실행하면 콘솔에 two가 출력된다. promise2가 100ms 후에 가장 먼저 이행되기 때문이다.

 

=> 결과값 > "two"