Promise 入門

# はじめに

[`Promise`](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise) は**非同期処理の最終的な完了もしくは失敗を表すオブジェクト**です。

Promise はコールバックを関数に渡すかわりに、関数が返したオブジェクトに対してコールバックを登録するようにする、というものです。

以下のコードは `createAudioFileAsync()` を使用したもの

```js
function successCallback(result) {
  console.log("Audio file ready at URL: " + result);
}

function failureCallback(error) {
  console.log("Error generating audio file: " + error);
}

createAudioFileAsync(audioSettings, successCallback, failureCallback);
```



最近では関数は Promise を返し、代わりにその Promise にコールバックを登録することができます。

```js
createAudioFileAsync(audioSettings).then(successCallback, failureCallback);
```

```js
const promise = createAudioFileAsync(audioSettings); 
promise.then(successCallback, failureCallback);
```



# メリット

- 現在の JavaScript イベントループの実行完了より前には、コールバックが決して呼び出されない。
- 非同期処理が完了もしくは失敗した後に `then()` により登録されたコールバックでも呼び出される。
- `then()` を何回も呼び出して複数のコールバックを追加してもよく、それぞれのコールバックは追加順に独立して実行される。



# Promise チェーン

**複数の非同期処理を順番に実行し、前の処理が完了してからその結果を次の処理で使う**ことができます。



`then()` 関数は元の Promise とは別の**新しい Promise** を返します。

```js
const promise = doSomething();
const promise2 = promise.then(successCallback, failureCallback);
```

または以下

```js
const promise2 = doSomething().then(successCallback, failureCallback);
```

2 つ目の Promise は `doSomething()` の完了を表すだけではなく、渡した `successCallback` もしくは `failureCallback` の完了も表す。

`promise2` に追加されたコールバックはいずれも Promise のキューにおいて、`successCallback` または `failureCallback` が返す Promise の後ろに追加されます。

基本的に、**それぞれの Promise はチェーン(連鎖)上の各非同期処理の完了を表します。**

Promiseを使わないと、複数の非同期処理を順番に実行するには、以下のようにする必要があった。

```js
// Promiseを使わないと分かりにくい
doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
      console.log('Got the final result: ' + finalResult);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);
```



モダンな関数を使えば、その代わりに戻り値の Promise にコールバックを付加して Promise チェーンとして記述できます。

```js
// 一般的なニーズとしては、複数の非同期処理を順番に実行し
// 「前の処理が完了してからその結果を次の処理で使う」
// というものがあります。これは Promise チェーンを作成することで行えます。

// SuccessCallBack(resulut) = function(result){return doSomethingElse(result);}
// Promise = doSomething 
// doSomething() の結果が result
// Promise = doSomething().then(function(result) {return doSomethingElse(result);})

doSomething().then(function(result) {
  return doSomethingElse(result);
})
.then(function(newResult) {
  return doThirdThing(newResult);
})
.then(function(finalResult) {
  console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);
```

 `then` 関数の引数はオプション(必須ではない)です。

また、**`catch(failureCallback)` は `then(null, failureCallback)` の短縮形です。**



# アロー関数

```js
//「前の処理が完了してからその結果を次の処理で使う」
//「doSomething()の結果」=「result」
//「doSomethingElse(result)の結果」=「newResult」
//「doSomethingThird(newResult)の結果」=「finalResult」

doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
  console.log(`Got the final result: ${finalResult}`);
})
.catch(failureCallback);
```

 (アロー関数を使った `() => x` は `() => { return x; }` の短縮形)



# catch後のチェーン

 `catch` の後にチェーンするのも可能です。

```js
new Promise((resolve, reject) => {
    console.log('Initial');

    resolve();
})
.then(() => {
    throw new Error('Something failed');
        
    console.log('Do this');
})
.catch(() => {
    console.log('Do that');
})
.then(() => {
    console.log('Do this whatever happened before');
});
```

これは下記のテキストを出力します。

```html
Initial
Do that
Do this whatever happened before
```



# 参考

https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Using_promises