# Promise.all 與 Promise.race

> Promise.all 與 Promise.race 的參數值，通常使用陣列結構作為傳入參數，而陣列中要不是就一般的值，要不就是 Promise 物件

`Promise.all`是"**並行運算**"使用的靜態方法，它的語法如下(出自[MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all)):

```javascript
Promise.all(iterable)
```

`iterable`代表可傳入陣列(Array)之類的物件，JavaScript 內建的有實作`iterable`協定的有 String、Array、TypedArray、Map 與 Set 這幾個物件。一般使用上都用到陣列而已。`Promise.all`方法會將陣列中的值並行運算執行，全部完成後才會接著下個`then`方法。在執行時有幾種情況:

* 陣列中的索引值與執行順序無關
* 陣列中的值如果不是 Promise 物件，會自動使用`Promise.resolve`方法來轉換
* 執行過程中只要有"**其中一個(any)**"陣列中的 Promise 物件執行發生錯誤例外，或是有 Promise 的 reject 情況，會立即回傳一個 rejected 狀態 promise 物件
* 實現完成後，接下來的 then 方法會獲取到的值是陣列值

```javascript
const p1 = Promise.resolve(3)
const p2 = 1337
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('foo'), 1000)
})

Promise.all([p1, p2, p3])
  .then(value => {
    console.log(value)
  })
  .catch(err => {
    console.log(err.message)
  })

//結果: [3, 1337, "foo"]
```

你可能會好奇，String(字串)類型是可以傳到`Promise.all`中的參數，傳入後會變成什麼樣子，當然實際上應該沒人這樣在用的。以下為一個簡單的範例:

```javascript
Promise.all('i am a string')
  .then(value => {
    console.log(value)
  })
  .catch(err => {
    console.log(err.message)
  })

//結果: ["i", " ", "a", "m", " ", "a", " ", "s", "t", "r", "i", "n", "g"]
```

`Promise.race`它的真正名稱應該是對比`Promise.all`的"any"，如果對`Promise.all`來說，指的是"**所有的**"陣列傳入參數的 Promise 物件都要解決(resolve)完了才進行下一步，`Promise.race`則是"**任何一個**"陣列傳入參數的 Promise 物件有解決，就會到下一步去。用"race(競賽)"這個字詞是比喻就像在賽跑一樣，只要有一個參賽者到達終點就行了，當然它的回傳值也只會是那個優勝者而已。

`Promise.race`的規則與`Promise.all`相同，只不過實現的話，下一步的`then`方法只會獲取跑最快的(最快實現的)的那個值，一個簡單的範例如下:

```javascript
const p1 = Promise.resolve(3)
const p2 = 1337
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('foo'), 1000)
})

Promise.race([p1, p2, p3])
  .then(value => {
    console.log(value)
  })
  .catch(err => {
    console.log(err.message)
  })
```

上面這個`Promise.race`範例，你把 p1 與 p2 的位置對調，就會發現最後的結果正好會對調，也就是說正好是只使用`Promise.resolve`方法的轉換情況，是和陣列中的前後順序有關的。不過因為`Promise.race`只能選出一個優腃者，p1 與 p2 應該算同時，所以也只能以陣列的順序為順序。

> 註: 所以用程式範例的結果來說，`Promise.race`應該要多一個規則，如果陣列中有同時實現的 promise 值，以陣列中的順序優先者為回傳值。

下面的例子是有加上每個陣列中的 Promise 物件產生時間的不同，這當然就只會回傳最快實現的那個 Promise 物件，也就是 p3。

```javascript
const p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('p1'), 2000)
})
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('p2'), 1000, 'p2')
})
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('p3'), 500, 'p3')
})

Promise.race([p1, p2, p3])
  .then(value => {
    console.log(value)
  })
  .catch(err => {
    console.log(err.message)
  })
```

> 註: 在 Promises/A+ 並沒有關於`Promise.all`或`Promise.race`的定義，它們是依據 ES6 Promise 標準的實作。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://eddy-chang.gitbook.io/javascript-start-es6-promise/zhu-yao-nei-rong/ch8_promise_all_n_race.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
