|
1 | 1 |
|
2 | | -The root of the problem is that `Promise.all` immediately rejects when one of its promises rejects, but it do nothing to cancel the other promises. |
| 2 | +문제의 원인은 `Promise.all`이 프라미스 중 하나라도 거부되면 즉시 거부되지만, 나머지 프라미스를 취소하지는 않는다는 데 있습니다. |
3 | 3 |
|
4 | | -In our case, the second query fails, so `Promise.all` rejects, and the `try...catch` block catches this error.Meanwhile, other promises are *not affected* - they independently continue their execution. In our case, the third query throws an error of its own after a bit of time. And that error is never caught, we can see it in the console. |
| 4 | +위 예시에서는 두 번째 쿼리가 실패하므로 `Promise.all`이 거부되고, `try...catch` 블록이 이 에러를 잡습니다. 한편 다른 프라미스는 *아무 영향도 받지 않습니다*. 각자 독립적으로 계속 실행됩니다. 예시에서는 잠시 후 세 번째 쿼리가 자체적으로 에러를 던집니다. 이 에러는 어디에서도 잡히지 않으므로 콘솔에서 확인할 수 있습니다. |
5 | 5 |
|
6 | | -The problem is especially dangerous in server-side environments, such as Node.js, when an uncaught error may cause the process to crash. |
| 6 | +이 문제는 Node.js 같은 서버 측 환경에서 특히 위험합니다. 잡히지 않은 에러로 인해 프로세스가 중단될 수 있기 때문입니다. |
7 | 7 |
|
8 | | -How to fix it? |
| 8 | +어떻게 고칠 수 있을까요? |
9 | 9 |
|
10 | | -An ideal solution would be to cancel all unfinished queries when one of them fails. This way we avoid any potential errors. |
| 10 | +가장 이상적인 해결책은 쿼리 중 하나가 실패했을 때 아직 끝나지 않은 쿼리를 모두 취소하는 것입니다. 이렇게 하면 잠재적인 에러를 피할 수 있습니다. |
11 | 11 |
|
12 | | -However, the bad news is that service calls (such as `database.query`) are often implemented by a 3rd-party library which doesn't support cancellation. Then there's no way to cancel a call. |
| 12 | +하지만 안타깝게도 `database.query` 같은 서비스 호출은 취소 기능을 지원하지 않는 서드파티 라이브러리로 구현된 경우가 많습니다. 이런 경우 호출을 취소할 방법이 없습니다. |
13 | 13 |
|
14 | | -As an alternative, we can write our own wrapper function around `Promise.all` which adds a custom `then/catch` handler to each promise to track them: results are gathered and, if an error occurs, all subsequent promises are ignored. |
| 14 | +대안으로 `Promise.all`을 감싸는 래퍼 함수를 직접 작성할 수 있습니다. 이 함수는 각 프라미스에 커스텀 `then/catch` 핸들러를 붙여 상태를 추적합니다. 결과를 모으다가 에러가 발생하면 그 이후 프라미스는 모두 무시합니다. |
15 | 15 |
|
16 | 16 | ```js |
17 | 17 | function customPromiseAll(promises) { |
18 | 18 | return new Promise((resolve, reject) => { |
19 | 19 | const results = []; |
20 | 20 | let resultsCount = 0; |
21 | | - let hasError = false; // we'll set it to true upon first error |
| 21 | + let hasError = false; // 첫 번째 에러가 발생하면 true로 바꿉니다. |
22 | 22 |
|
23 | 23 | promises.forEach((promise, index) => { |
24 | 24 | promise |
25 | 25 | .then(result => { |
26 | | - if (hasError) return; // ignore the promise if already errored |
| 26 | + if (hasError) return; // 이미 에러가 발생했다면 이 프라미스를 무시합니다. |
27 | 27 | results[index] = result; |
28 | 28 | resultsCount++; |
29 | 29 | if (resultsCount === promises.length) { |
30 | | - resolve(results); // when all results are ready - successs |
| 30 | + resolve(results); // 모든 결과가 준비되면 성공입니다. |
31 | 31 | } |
32 | 32 | }) |
33 | 33 | .catch(error => { |
34 | | - if (hasError) return; // ignore the promise if already errored |
35 | | - hasError = true; // wops, error! |
36 | | - reject(error); // fail with rejection |
| 34 | + if (hasError) return; // 이미 에러가 발생했다면 이 프라미스를 무시합니다. |
| 35 | + hasError = true; // 에러가 발생했습니다. |
| 36 | + reject(error); // 거부 상태로 실패 처리합니다. |
37 | 37 | }); |
38 | 38 | }); |
39 | 39 | }); |
40 | 40 | } |
41 | 41 | ``` |
42 | 42 |
|
43 | | -This approach has an issue of its own - it's often undesirable to `disconnect()` when queries are still in the process. |
| 43 | +이 방식에도 문제가 있습니다. 쿼리가 아직 처리 중일 때 `disconnect()`를 호출하는 것은 대개 바람직하지 않습니다. |
44 | 44 |
|
45 | | -It may be important that all queries complete, especially if some of them make important updates. |
| 45 | +특히 일부 쿼리가 중요한 업데이트를 수행한다면 모든 쿼리가 완료되는 것이 중요할 수 있습니다. |
46 | 46 |
|
47 | | -So we should wait until all promises are settled before going further with the execution and eventually disconnecting. |
| 47 | +따라서 실행을 계속 진행하고 마지막에 연결을 끊기 전에 모든 프라미스가 처리될 때까지 기다려야 합니다. |
48 | 48 |
|
49 | | -Here's another implementation. It behaves similar to `Promise.all` - also resolves with the first error, but waits until all promises are settled. |
| 49 | +다른 구현을 살펴봅시다. 이 구현은 `Promise.all`과 비슷하게 동작합니다. 첫 번째 에러와 함께 거부되지만, 모든 프라미스가 처리될 때까지 기다립니다. |
50 | 50 |
|
51 | 51 | ```js |
52 | 52 | function customPromiseAllWait(promises) { |
@@ -80,16 +80,16 @@ function customPromiseAllWait(promises) { |
80 | 80 | } |
81 | 81 | ``` |
82 | 82 |
|
83 | | -Now `await customPromiseAllWait(...)` will stall the execution until all queries are processed. |
| 83 | +이제 `await customPromiseAllWait(...)`는 모든 쿼리가 처리될 때까지 실행을 멈춥니다. |
84 | 84 |
|
85 | | -This is a more reliable approach, as it guarantees a predictable execution flow. |
| 85 | +실행 흐름을 예측할 수 있게 보장하므로 더 안정적인 방식입니다. |
86 | 86 |
|
87 | | -Lastly, if we'd like to process all errors, we can use either use `Promise.allSettled` or write a wrapper around it to gathers all errors in a single [AggregateError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError) object and rejects with it. |
| 87 | +마지막으로 모든 에러를 처리하고 싶다면 `Promise.allSettled`를 사용하면 됩니다. 또는 `Promise.allSettled`를 감싸는 래퍼를 작성해 모든 에러를 하나의 [AggregateError](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/AggregateError) 객체에 모아 거부할 수도 있습니다. |
88 | 88 |
|
89 | 89 | ```js |
90 | | -// wait for all promises to settle |
91 | | -// return results if no errors |
92 | | -// throw AggregateError with all errors if any |
| 90 | +// 모든 프라미스가 처리될 때까지 기다립니다. |
| 91 | +// 에러가 없으면 결과를 반환합니다. |
| 92 | +// 에러가 하나라도 있으면 모든 에러가 담긴 AggregateError를 던집니다. |
93 | 93 | function allOrAggregateError(promises) { |
94 | 94 | return Promise.allSettled(promises).then(results => { |
95 | 95 | const errors = []; |
|
0 commit comments