私が async/await、promise をちゃんと理解するまでのステップ１，２，３

# これは何？

- javascript の async/await を使いこなすために必要な事柄について、私なりに説明したものです。

# 書いてあること

- ステップ１）await 使えば待ってくれる
    - 必要最小限の async/await、及び、エラーの catch の話 

- ステップ２）promise というもの
    - promise の中には「正常データ = resolve」と「エラー = reject」のいずれかを保管できるという話
    - どうすれば、promise から、正常データ(resolve)を取り出せるか？
    - どうすれば、promise から、エラー(reject)を取り出せるか？
    - Promise.all の話

- ステップ３）promiseを作る方法
    - callbackスタイルの関数を、promiseスタイルとして使う方法
    - setTimeout() を promiseスタイルにする
    - async で promise を作ってみる

- あと、参考にしたURLと、検証の為に作ったサンプルソースを付けてます。

# ステップ１）await 使えば待ってくれる

- `http://.../get1` を取得した後、`http://.../get2` を取得する。
- つまり、１つ１つの処理を待ちます。（同時に動いたりしません）

```javascript
async function xxx() {

  // このgetでデータ取得が完了するまで待ってから・・・
  const res1 = await axios.get('http://.../get1');
  console.log(res1);

  // 次のgetを開始する。
  const res2 = await axios.get('http://.../get2');
  console.log(res2);
}
```
- もしも、`await` を書かなかったら、一瞬でこの関数の処理は終わってしまい `console.log` の出力は `res1=Promise` `res2=Promise` になってしまいます。（Promise の説明はステップ２を参照ください）
    - つまり、値が `Promise` になってしまったときは、`await` のつけ忘れを疑えばいい。
- `await` を使ったときは、関数名に `async` というおまじないが必要なので注意
    - うっかり忘れると、`async` が無いと怒られます。素直に `async` を付けましょう。
    - 実は `async` の本当の意味は、「この関数は、promise を返しますよ」という宣言なのですが、ひとまず＊おまじない＊と理解しておいて構わないです。

## 少し昔 (async/await が無かった時)は、then を使ってた

- 同じ処理を async/await を使わずに書いてみます。

```javascript
function xxx() {
  axios.get('http://.../get1')
    .then((res1) => {
      // get1のデータが取得できたら、ここの処理開始
      console.log(res1);
      return(axios.get('http://.../get2'));
    })
    .then((res2) => {
      // get2のデータが取得できたら、ここの処理開始
      console.log(res2);
    });
}
```

- async/await の記述の方が簡単ですね。

- 余談ですが、、、
    - もっと昔は、callbackスタイルで非同期処理を行ってました。
    - 今現在も、`fs.read()` などの多くの標準関数が、callbackスタイルです。
    - 後で書きますが、callbackスタイルの関数も、簡単にpromiseスタイルに変換できるので、`await` も使えます。

## async/await で エラーを扱う方法は？

- 正常処理は良いとして、エラーはどのように扱えばいいんでしょうか。
- ここでは「getでエラー発生したとき、処理を中断して関数を抜ける」方法を考えます。

## try/catch でエラーをとらえる

- async/await を使っていても、特別な書き方にはなりません。
- 普通に try/catch が使えます。

```javascript
async function xxx() {
  let res1;
  let res2;
  try {
    res1 = await axios.get('http://.../get1');
    res2 = await axios.get('http://.../get2');
  } catch(err) {
    console.log('get1 or get2 error'); //・・・どちらか一方でもエラー発生した場合
    return;
  }
  console.log(res1);
  console.log(res2);
}
```

- もしも、get1、get2 で別々にエラーをとらえたいなら、それぞれに try/catch を書けばいいでしょう。

# ステップ２）promise というもの

- **実は、`axios.get(url)` は promise を返してきます。**
- 「え？急に何のこと言ってるの？」と思った人へ
    - 実は「`axios.get(url)` は取得したデータが返って**きません**」
    - promise というモノが返ってくるんです。
    - あとで詳しく書きますが、例えば「頭に `await` を付けて `await axios.get(url)` とすると、取得したデータが返ってきます」
- **promise の中には、「正常データ」と「エラー」のどちらかを保管できるようになっています。**
    - promise流に言うと「正常データ」は「resolve」、「エラー」は「reject」と呼びます。
- 余談ですが、、、
    - ところで **「既に、returnで正常データを、throwでエラーを返すという仕組みがあるにもかかわらず、なぜ、promiseにわざわざ、正常データとエラーを詰め込まなければならないのでしょうか？」**
    - promiseは、非同期処理の結果(正常データ、エラー)を、javascriptの言語仕様として、どう扱うか決めたものです。その成果として、さらに簡単に非同期を扱えるようになった、async/awaitの存在があります。
    - つまり、promise ができたから、さらに進化して async/await が誕生したんです。
    - 5/1追記。さらに興味のある方は、コメント欄の yuta0801 さんの書き込みや、[「非同期処理 · JavaScriptの入門書 #jsprimer」]( https://jsprimer.net/basic/async/) を読むと、より理解が深まると思います。


## どうすれば、promise から、正常データ(resolve)を取り出せるか？

- ２つ方法があります。
- 方法１）`await` をつける。
    - 例えば `ret = await axios.get(url)` と書けば、正常データ(ret)が取り出せます。
- 方法２）promise の `then` メソッドを使う。
    - 例えば `axios.get(url).then(ret => { <retを使った処理> })` と書けば、正常データ(ret)が取り出せます。

## どうすれば、promise から、エラー(reject)を取り出せるか？

- ２つ方法があります。
- 方法１）普通に try/catch を使う。
    - `try { <promiseから正常データを取り出す処理> } catch(err) { <エラー処理> }`
- 方法２）promise の `.catch` メソッドを使う。
    - `<promiseから正常データを取り出す処理>.catch(err => { <エラー処理> })`

## 例）await で正常データを取得して、try/catch でエラーを取り出す

- 先の「try/catch でエラーをとらえる」に書いた通りです。

## 例）await で正常データを取得して、promise の .catch でエラーを取り出す

- 回りくどいですが、まずは、私が最初にこの方法で書いたときの **間違ったコード** を載せておきます。
- といっても、promiseの使い方とかそういう次元ではなく、javascript そのものの理解度が足りずに間違って書いてしまったので、恥ずかしいミスなのですが。

```javascript
async function xxx() {
  const res1 = await axios.get('http://.../get1')
    .catch((err) => {
      console.log('get1 error');
      return; // ・・・エラーだったら中断して関数を抜ける為のreturnの＊つもり＊だが、
    });
  console.log(res1); // ・・・実はこれ以降も実行される。res1=undefined になる。

  const res2 = await axios.get('http://.../get2');
    .catch((err) => {
      console.log('get1 error');
      return; // ・・・エラーだったら中断して関数を抜ける為のreturnの＊つもり＊
    });
  console.log(res2); // ・・・実はこれ以降も実行される。res2=undefined になる。
}
```

- エラー発生を `catch` で受けて、**xxx関数を抜ける為にreturnしたつもり** ですが、この記述では **無名関数を抜けるだけで、xxx関数は抜けられません。**
    - 代替え案としては、`throw new Error('error')` を使えば、一気にxxx関数を抜けられます。

# そもそも、非同期で動くことが出来る axios.get を処理を待って順次実行(同期実行)するのは、もったいないのでは？

- ということで、複数の axios.get を同時に実行(非同期実行)して、全部の処理が完了するまで待ってみます。
    - 例えば、１つの axios.get に１秒かかるとして、３つ実行した場合、、、
        - 同期実行：「axios.getを待つ → axios.getを待つ → axios.getを待つ」ので、計３秒かかります。
        - 非同期実行：「axios.getｘ3を同時に実行 → 全部終わるのを待つ」ので、計１秒で済みます。

```javascript
async function xxx() {
  let res1;
  let res2;
  let res3;
  try {
    [res1, res2, res3] = await Promise.all([
      axios.get('http://.../get1').catch(e => { throw 'get1 error '+e.message}),
      axios.get('http://.../get2').catch(e => { throw 'get2 error '+e.message}),
      axios.get('http://.../get3').catch(e => { throw 'get3 error '+e.message}),
    ]);
  } catch(err) {
    console.log(err);
    return; // １つでもエラーになったら、関数を抜ける
  }

  // ３つ全てが正常データを取得できたとき、以下を実行
  console.log(res1);
  console.log(res2);
  console.log(res3);
}
```

- `Promise.all` を使うことで、３つの axios.get を同時に実行開始し、３つとも完了するのを待つことが出来ます。
- この例では、各 axios.get に catch を付けることで、どちらのエラーが発生したか判別できるように、エラーを書き換えています。
    - しかしながら、単に、エラー検出するだけなら、外側の try/catch だけで十分です。

# ステップ３）promiseを作る方法

## callbackスタイル を promiseスタイルにする

- promise が発明される以前、非同期と言えば callbackスタイル が一般的でした。
- これらの関数を promise 化してみます。

```javascript
const readFileAsync = util.promisify(fs.readFile);
text = await readFileAsync(path);
```

- `util.promisify` を使うと、promiseスタイルの関数を得られます。
    - 他にも bluebird などでも提供されています。


## setTimeout() を promiseスタイルにする

### 例）msec後に、正常データ('ok')を返す promise

```javascript
function sleep_ok(msec) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('>>> sleep_ok() ---> resolve(ok)');
      resolve('ok');
    }, msec);
  });
}
```

### 例）msec後に、エラー(new Error('ng'))を返す promise

```javascript
function sleep_ng(msec) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('>>> sleep_ng() ---> reject(new Error(ng))');
      reject(new Error('ng'));
    }, msec);
  });
}
```

## async で promise を作ってみる

- 「async は promise を返す」ということは、「async で promise を作れる」ということです。

### 「async の return」は「promise の resolve」と等価

```javascript
async function async_ok() {
  console.log('>>> async_ok() ---> return(ok)');
  return 'ok'; // promise の resolve と等価
}
```

### 「async の throw」は「promise の reject」と等価

```javascript
async function async_ng() {
  console.log('>>> async_ng() ---> throw new Error(ng)');
  throw new Error('ng'); // promise の reject と等価
}
```

# 参照したURL

- javascript の非同期処理について、学ぶにあたって参照させて頂いたURLです。皆さんありがとうございます。

- コールバックスタイルの非同期処理をpromise化するモジュールの話
	- util.promisify()でcallbackスタイルの関数をpromise化 - Qiita https://qiita.com/t-okushima/items/fbca67541003576997cc

- 標準のpromiseより、さらに高機能なものの話
	- PromiseとQとBluebird - Qiita https://qiita.com/kamijin_fanta/items/21a061a00575f0a357c6

- Array の map、filter で async/await を使ったときに、うまく動かすことが出来ず、参考にさせてもらいました。
	- Array 操作関数の callback に async/await な関数を指定したい - Qiita https://qiita.com/janus_wel/items/1dc491d866f49af76e98

- コンパクトにまとめられた説明です。async の正体を教えてもらいました。
	- async/await 入門（JavaScript） - Qiita https://qiita.com/soarflat/items/1a9613e023200bbebcb3

- 長文ですが、とても詳しい説明です。このレベルの情報がネットで簡単に見られるのは助かります。
	- 非同期処理 · JavaScriptの入門書 #jsprimer https://jsprimer.net/basic/async/



# 参考）サンプルソース

- ここまでの説明の為に作ったサンプルソースです。
- node.js v10.15.3 を使いました。

## run.sh

```sh:run.sh
set -x

:
: --------------------------------
: async/await の例
: --------------------------------
node --experimental-modules promise.mjs sample11
node --experimental-modules promise.mjs sample12
node --experimental-modules promise.mjs sample13
node --experimental-modules promise.mjs sample14
node --experimental-modules promise.mjs sample15

:
: --------------------------------
: promise の then/catch の例
: --------------------------------
node --experimental-modules promise.mjs sample21
node --experimental-modules promise.mjs sample24
node --experimental-modules promise.mjs sample25

:
: --------------------------------
: promise の resolve/reject は
: async の return/throw と等価である
: --------------------------------
node --experimental-modules promise.mjs sample31
node --experimental-modules promise.mjs sample32

:
: --------------------------------
: Promise.all の例
: --------------------------------
node --experimental-modules promise.mjs sample41
node --experimental-modules promise.mjs sample42
node --experimental-modules promise.mjs sample43
node --experimental-modules promise.mjs sample44
node --experimental-modules promise.mjs sample45
```

## myutil.mjs

```javascript:myutil.mjs
export function log(...msg) {
  const dt = new Date();
  const ms = dt.getMinutes() + ':' + dt.getSeconds();
  console.log(ms, ...msg);
}

export function sleep_ok(msec) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      log('>>> sleep_ok() ---> resolve(ok)');
      resolve('ok');
    }, msec);
  });
}

export function sleep_ng(msec) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      log('>>> sleep_ng() ---> reject(new Error(ng))');
      reject(new Error('ng'));
    }, msec);
  });
}

// msec後、consoleにlogmsgを出力して、`resolve(ret)` する。
// ただし、retがErrorのとき、`rejecti(ret)` する。
export function sleep(msec, logmsg, ret) {
  log('>>> sleep() ' + logmsg + ' in.');
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (ret instanceof Error) {
        log('>>> sleep() ' + logmsg + ' out reject()');
        reject(ret);  // Error のとき reject
      } else {
        log('>>> sleep() ' + logmsg + ' out resolve()');
        resolve(ret);
      }
    }, msec);
  });
}
```
## promise.mjs

```javascript:promise.mjs
import {log, sleep_ok, sleep_ng} from './myutil.mjs'

async function sample11() {
  console.log('// await で待つ');
  log('-- 1');
  log(await sleep_ok(1000));
  log('-- 2');
  log(await sleep_ok(1000));
  log('-- 3');
}

function sample12() {
  console.log('// もしも、await をつけなかったら？');
  log('-- 1');
  log(sleep_ok(1000));
  log('-- 2');
  log(sleep_ok(1000));
  log('-- 3');
}

async function sample13() {
  console.log('// エラーだったら？(rejectされたら？)');
  log('-- 1');
  log(await sleep_ok(1000));
  log('-- 2');
  log(await sleep_ng(1000));
  log('-- ここには到達しない');
}

async function sample14() {
  console.log('// エラーをtry/catchしてみる');
  log('-- 1');
  log(await sleep_ok(1000));
  log('-- 2');
  try {
    log(await sleep_ng(1000));
  } catch (e) {
    log('-- 3 try/catch() e.message=' + e.message);
  }
  log('-- 4');
}

async function sample15() {
  console.log('// エラー発生で即関数を抜ける');
  try {
    log('-- 1');
    log(await sleep_ok(1000));
    log('-- 2');
    log(await sleep_ng(1000));
    log('-- ここには到達しない');
  } catch (e) {
    log('-- 3 try/catch() e.message=' + e.message);
    log('-- 4 return');
    return;
  }
  log('-- ここには到達しない');
}

function sample21() {
  console.log('// sample11 を promiseのthen で記述してみる');
  log('-- 1');
  sleep_ok(1000)
    .then((ret) => {
      log(ret);
      log('-- 3');
      return(sleep_ok(1000));
    })
    .then((ret) => {
      log(ret);
      log('-- 4');
    });
  log('-- 2 これが2になる。4の次にはならないので注意');
}

function sample24() {
  console.log('// sample14 を promiseのthen/catch で記述してみる');
  log('-- 1');
  sleep_ok(1000)
    .then((ret) => {
      log(ret);
      log('-- 3');
      return(sleep_ng(1000));
    })
    .then((ret) => {
      log(ret);
      log('-- ここには到達しない');
    })
    .catch((err) => {
      log('--4 catch() err.message=' + err.message);
    });
  log('-- 2 これが2になる。4の次にはならないので注意');
}

function sample25() {
  console.log('// sample15 を promiseのthen/catch で記述してみる');
  log('-- 1');
  sleep_ok(1000)
    .then((ret) => {
      log(ret);
      log('-- 3');
      return(sleep_ng(1000));
    })
    .then((ret) => {
      log(ret);
      log('-- ここには到達しない');
    })
    .catch((err) => {
      log('--4 catch() err.message=' + err.message);
      log('--5 ここにreturnと書いても、親関数を抜ける意味にはならないので注意');
      return;
    });
  log('-- 2 ついつい「5でreturnしているので、ここには到達しない」と考えてしまうが、そうはならないので注意');
}

async function async_ok() {
  log('>>> async_ok() ---> return(ok)');
  return 'ok'; // promise の resolve と等価
}

async function async_ng() {
  log('>>> async_ng() ---> throw new Error(ng)');
  throw new Error('ng'); // promise の reject と等価
}

async function sample31() {
  console.log('// 「promise の resolve」は「async の return」と等価');
  log('-- 1');
  log(await async_ok());
  log('-- 2');
  log(await sleep_ok(0));
  log('-- 3');
}

async function sample32() {
  console.log('// 「promise の reject」は「async の throw」と等価');
  log('-- 1');
  try {
    await async_ng();
  } catch(err) {
    log('-- 2 catch() err.message=' + err.message);
  }
  log('-- 3');
  try {
    await sleep_ng(0);
  } catch(err) {
    log('-- 4 catch() err.message=' + err.message);
  }
  log('-- 5');
}

async function sample41() {
  console.log('// Promise.all で待つ');
  log('-- 1');
  let ret = await Promise.all([
    sleep_ok(1000),
    sleep_ok(2000)
  ]);
  log(ret);
  log('-- 2');
}
  
async function sample42() {
  console.log('// Promise.all で、ngがあるとき');
  log('-- 1');
  let ret = await Promise.all([
    sleep_ok(1000),
    sleep_ng(2000)
  ]);
  log('-- ここには到達しない');
  log(ret);
}
 
async function sample43() {
  console.log('// Promise.all で try/catch');
  log('-- 1');
  let ret;
  try {
    ret = await Promise.all([
      sleep_ok(1000),
      sleep_ng(2000)
    ]);
  } catch(err) { // どちらの処理のエラーかはわからない。(errの戻り値を工夫する必要あり)
    log('-- 2 catch() err.message=' + err.message);
    return; // ここで処理抜ける
  }
  log('-- ここには到達しない');
  log(ret);
}
 
async function sample44() {
  console.log('// Promise.all の try/catch で promise を直接見れば、どれのエラーか判別できる？');
  log('-- 1');
  let p = Promise.all([
    sleep_ok(1000),
    sleep_ng(2000)
  ]);
  let ret;
  try {
    ret = await p;
  } catch(err) {
    log('-- 2 catch() err.message=' + err.message);
    log('p=', p); // 判別できない
    return; // ここで処理抜ける
  }
  log('-- ここには到達しない');
  log(ret);
}
 
async function sample45() {
  console.log('// 個々のpromiseにcatchをつけ、ユニークなthrowとすることで誰がエラーになったか判別する');
  log('-- 1');
  let ret;
  try {
    ret = await Promise.all([
      sleep_ok(1000).catch(err => { throw new Error('sleep_ok(1000)') }),
      sleep_ng(2000).catch(err => { throw new Error('sleep_ng(2000)') })
    ]);
  } catch(err) {
    log('-- 2 catch() err.message=' + err.message);
    return; // ここで処理抜ける
  }
  log('-- ここには到達しない');
  log(ret);
}
 

const funcname = process.argv[2] + '()';
console.log('');
console.log('### ' + funcname);
eval(funcname);
```

## 実行結果

```console
ubuntu@ubuntu201809:~/20190427node$ ./run.sh |& cat -n
     1	++ :
     2	++ : --------------------------------
     3	++ : async/await の例
     4	++ : --------------------------------
     5	++ node --experimental-modules promise.mjs sample11
     6	(node:11925) ExperimentalWarning: The ESM module loader is experimental.
     7	
     8	### sample11()
     9	// await で待つ
    10	5:23 -- 1
    11	5:24 >>> sleep_ok() ---> resolve(ok)
    12	5:24 ok
    13	5:24 -- 2
    14	5:25 >>> sleep_ok() ---> resolve(ok)
    15	5:25 ok
    16	5:25 -- 3
    17	++ node --experimental-modules promise.mjs sample12
    18	(node:11936) ExperimentalWarning: The ESM module loader is experimental.
    19	
    20	### sample12()
    21	// もしも、await をつけなかったら？
    22	5:25 -- 1
    23	5:25 Promise { <pending> }
    24	5:25 -- 2
    25	5:25 Promise { <pending> }
    26	5:25 -- 3
    27	5:26 >>> sleep_ok() ---> resolve(ok)
    28	5:26 >>> sleep_ok() ---> resolve(ok)
    29	++ node --experimental-modules promise.mjs sample13
    30	(node:11947) ExperimentalWarning: The ESM module loader is experimental.
    31	
    32	### sample13()
    33	// エラーだったら？(rejectされたら？)
    34	5:27 -- 1
    35	5:28 >>> sleep_ok() ---> resolve(ok)
    36	5:28 ok
    37	5:28 -- 2
    38	5:29 >>> sleep_ng() ---> reject(new Error(ng))
    39	(node:11947) UnhandledPromiseRejectionWarning: Error: ng
    40	    at Timeout.setTimeout [as _onTimeout] (file:///home/ubuntu/20190427node/myutil.mjs:20:14)
    41	    at ontimeout (timers.js:436:11)
    42	    at tryOnTimeout (timers.js:300:5)
    43	    at listOnTimeout (timers.js:263:5)
    44	    at Timer.processTimers (timers.js:223:10)
    45	(node:11947) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
    46	(node:11947) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
    47	++ node --experimental-modules promise.mjs sample14
    48	(node:11958) ExperimentalWarning: The ESM module loader is experimental.
    49	
    50	### sample14()
    51	// エラーをtry/catchしてみる
    52	5:29 -- 1
    53	5:30 >>> sleep_ok() ---> resolve(ok)
    54	5:30 ok
    55	5:30 -- 2
    56	5:31 >>> sleep_ng() ---> reject(new Error(ng))
    57	5:31 -- 3 try/catch() e.message=ng
    58	5:31 -- 4
    59	++ node --experimental-modules promise.mjs sample15
    60	(node:11969) ExperimentalWarning: The ESM module loader is experimental.
    61	
    62	### sample15()
    63	// エラー発生で即関数を抜ける
    64	5:31 -- 1
    65	5:32 >>> sleep_ok() ---> resolve(ok)
    66	5:32 ok
    67	5:32 -- 2
    68	5:33 >>> sleep_ng() ---> reject(new Error(ng))
    69	5:33 -- 3 try/catch() e.message=ng
    70	5:33 -- 4 return
    71	++ :
    72	++ : --------------------------------
    73	++ : promise の then/catch の例
    74	++ : --------------------------------
    75	++ node --experimental-modules promise.mjs sample21
    76	(node:11980) ExperimentalWarning: The ESM module loader is experimental.
    77	
    78	### sample21()
    79	// sample11 を promiseのthen で記述してみる
    80	5:33 -- 1
    81	5:33 -- 2 これが2になる。4の次にはならないので注意
    82	5:34 >>> sleep_ok() ---> resolve(ok)
    83	5:34 ok
    84	5:34 -- 3
    85	5:35 >>> sleep_ok() ---> resolve(ok)
    86	5:35 ok
    87	5:35 -- 4
    88	++ node --experimental-modules promise.mjs sample24
    89	(node:11991) ExperimentalWarning: The ESM module loader is experimental.
    90	
    91	### sample24()
    92	// sample14 を promiseのthen/catch で記述してみる
    93	5:35 -- 1
    94	5:35 -- 2 これが2になる。4の次にはならないので注意
    95	5:36 >>> sleep_ok() ---> resolve(ok)
    96	5:36 ok
    97	5:36 -- 3
    98	5:37 >>> sleep_ng() ---> reject(new Error(ng))
    99	5:37 --4 catch() err.message=ng
   100	++ node --experimental-modules promise.mjs sample25
   101	(node:12002) ExperimentalWarning: The ESM module loader is experimental.
   102	
   103	### sample25()
   104	// sample15 を promiseのthen/catch で記述してみる
   105	5:37 -- 1
   106	5:37 -- 2 ついつい「5でreturnしているので、ここには到達しない」と考えてしまうが、そうはならないので注意
   107	5:38 >>> sleep_ok() ---> resolve(ok)
   108	5:38 ok
   109	5:38 -- 3
   110	5:39 >>> sleep_ng() ---> reject(new Error(ng))
   111	5:39 --4 catch() err.message=ng
   112	5:39 --5 ここにreturnと書いても、親関数を抜ける意味にはならないので注意
   113	++ :
   114	++ : --------------------------------
   115	++ : promise の resolve/reject は
   116	++ : async の return/throw と等価である
   117	++ : --------------------------------
   118	++ node --experimental-modules promise.mjs sample31
   119	(node:12013) ExperimentalWarning: The ESM module loader is experimental.
   120	
   121	### sample31()
   122	// 「promise の resolve」は「async の return」と等価
   123	5:39 -- 1
   124	5:39 >>> async_ok() ---> return(ok)
   125	5:39 ok
   126	5:39 -- 2
   127	5:39 >>> sleep_ok() ---> resolve(ok)
   128	5:39 ok
   129	5:39 -- 3
   130	++ node --experimental-modules promise.mjs sample32
   131	(node:12024) ExperimentalWarning: The ESM module loader is experimental.
   132	
   133	### sample32()
   134	// 「promise の reject」は「async の throw」と等価
   135	5:40 -- 1
   136	5:40 >>> async_ng() ---> throw new Error(ng)
   137	5:40 -- 2 catch() err.message=ng
   138	5:40 -- 3
   139	5:40 >>> sleep_ng() ---> reject(new Error(ng))
   140	5:40 -- 4 catch() err.message=ng
   141	5:40 -- 5
   142	++ :
   143	++ : --------------------------------
   144	++ : Promise.all の例
   145	++ : --------------------------------
   146	++ node --experimental-modules promise.mjs sample41
   147	(node:12035) ExperimentalWarning: The ESM module loader is experimental.
   148	
   149	### sample41()
   150	// Promise.all で待つ
   151	5:40 -- 1
   152	5:41 >>> sleep_ok() ---> resolve(ok)
   153	5:42 >>> sleep_ok() ---> resolve(ok)
   154	5:42 [ 'ok', 'ok' ]
   155	5:42 -- 2
   156	++ node --experimental-modules promise.mjs sample42
   157	(node:12046) ExperimentalWarning: The ESM module loader is experimental.
   158	
   159	### sample42()
   160	// Promise.all で、ngがあるとき
   161	5:42 -- 1
   162	5:43 >>> sleep_ok() ---> resolve(ok)
   163	5:44 >>> sleep_ng() ---> reject(new Error(ng))
   164	(node:12046) UnhandledPromiseRejectionWarning: Error: ng
   165	    at Timeout.setTimeout [as _onTimeout] (file:///home/ubuntu/20190427node/myutil.mjs:20:14)
   166	    at ontimeout (timers.js:436:11)
   167	    at tryOnTimeout (timers.js:300:5)
   168	    at listOnTimeout (timers.js:263:5)
   169	    at Timer.processTimers (timers.js:223:10)
   170	(node:12046) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
   171	(node:12046) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
   172	++ node --experimental-modules promise.mjs sample43
   173	(node:12057) ExperimentalWarning: The ESM module loader is experimental.
   174	
   175	### sample43()
   176	// Promise.all で try/catch
   177	5:44 -- 1
   178	5:45 >>> sleep_ok() ---> resolve(ok)
   179	5:46 >>> sleep_ng() ---> reject(new Error(ng))
   180	5:46 -- 2 catch() err.message=ng
   181	++ node --experimental-modules promise.mjs sample44
   182	(node:12069) ExperimentalWarning: The ESM module loader is experimental.
   183	
   184	### sample44()
   185	// Promise.all の try/catch で promise を直接見れば、どれのエラーか判別できる？
   186	5:46 -- 1
   187	5:47 >>> sleep_ok() ---> resolve(ok)
   188	5:48 >>> sleep_ng() ---> reject(new Error(ng))
   189	5:48 -- 2 catch() err.message=ng
   190	5:48 p= Promise {
   191	  <rejected> Error: ng
   192	      at Timeout.setTimeout [as _onTimeout] (file:///home/ubuntu/20190427node/myutil.mjs:20:14)
   193	      at ontimeout (timers.js:436:11)
   194	      at tryOnTimeout (timers.js:300:5)
   195	      at listOnTimeout (timers.js:263:5)
   196	      at Timer.processTimers (timers.js:223:10) }
   197	++ node --experimental-modules promise.mjs sample45
   198	(node:12080) ExperimentalWarning: The ESM module loader is experimental.
   199	
   200	### sample45()
   201	// 個々のpromiseにcatchをつけ、ユニークなthrowとすることで誰がエラーになったか判別する
   202	5:48 -- 1
   203	5:49 >>> sleep_ok() ---> resolve(ok)
   204	5:50 >>> sleep_ng() ---> reject(new Error(ng))
   205	5:50 -- 2 catch() err.message=sleep_ng(2000)
ubuntu@ubuntu201809:~/20190427node$ 
```