【JavaScript】非同期処理⑤　Promiseと並列処理


#はじめに

Udemyの[【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)の講座の振り返りです。

前回の記事

https://qiita.com/nao0725/items/2d57cb954a43538af33e


#目的

* 非同期処理についての理解を深める

#本題
###1.並列処理

**前提**

```js
function sleep(val) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      console.log(val++);
      resolve(val);
       // このようにすることでループを重ねるごとに表示が遅れる
    }, val * 500);
  });
}

//Promiseチェーンしている
sleep(0).then(function(val) {
  return sleep(val);
}).then(function(val) {
  return sleep(val);
}).then(function(val) {
  return sleep(val);
})
````

####例1

並列処理の書き方

```js
function sleep(val) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      console.log(val++);
      resolve(val);
    }, val * 500);
  });
}

// Promise.allとして（）内に反復可能オブジェクトを入れる
// Promise.allが配列に格納されたPromiseのインスタンスが全て完了するまで次のthenメソッドを待つ
Promise.all([sleep(2), sleep(3), sleep(4)])
  .then(function(){
  // 2,3,4,endと出力
  // endが一番最後
  console.log("end");
});
`````

thenメソッドの関数に引数を渡す

```js
function sleep(val) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      console.log(val++);
      resolve(val);
    }, val * 500);
  });
}

Promise.all([sleep(2), sleep(3), sleep(4)])
// 引数dataを渡す
  .then(function(data){
    // dataを出力すると配列となってresolveで渡された結果が帰ってくる
  console.log(data);
});
`````

####例2

Promiseチェーンの中でPromise.allを使う

```js
function sleep(val) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      console.log(val++);
      resolve(val);
    }, val * 500);
  });
}

Promise.all([sleep(2), sleep(3), sleep(4)])
  .then(function(data){
  console.log(data);
});
sleep(0).then(function(val) {
  // 上記のPromise.allの部分を下記のreturnのところで置換する
  // 次のthenメソッドも下記Promiseの処理が終わってから処理される
  return Promise.all([sleep(2), sleep(3), sleep(4)])
}).then(function(val) {
  // 出力すると先のPromisee.allの値が全て返ってくる
  console.log(val)
  return sleep(val);
}).then(function(val) {
  return sleep(val);
})
`````

####例3

Promise.raceで配列の中のどれか一つが呼ばれた時点でthenメソッドに処理が移行する

````js
function sleep(val) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      console.log(val++);
      resolve(val);
    }, val * 500);
  });
}

// コンソールに2,3,3,4と出力される
// sleep(2)が実行された時点で、次の処理に移行
// 2で引数に渡しているので,上記のval++で+1されるので3と出力される
Promise.race([sleep(2), sleep(3), sleep(4)])
  .then(function(data){
  console.log(data);
});
```

####例4

Promise.allSettledの使い方

```js
function sleep(val) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      console.log(val++);
      resolve(val);
    }, val * 500);
  });
}


Promise.allSettled([sleep(2), sleep(3), sleep(4)])
  .then(function(data){
  console.log(data);
});
`````

下記のように出力される

````console.
(3) [{…}, {…}, {…}]
0: status: "fulfilled"
   value: 3
   [[Prototype]]: Object

1: status: "fulfilled"
   value: 4
   [[Prototype]]: Object

2: status: "fulfilled"
   value: 5
   [[Prototype]]: Object

length: 3
[[Prototype]]: Array(0)
`````

fulfilledというのはresolveが呼ばれたタイミングのステータスを表している

もしrejectが呼ばれた場合はステータスがrejectedに変更される

````js
function sleep(val) {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      console.log(val++);
      // reject に変更
      reject(val);
    }, val * 500);
  });
}


Promise.all([sleep(2), sleep(3), sleep(4)])
  .then(function(data){
  console.log(data);
}).catch(function(e){
  // この場合catchの処理にエラーの表示が出る
  // allSettleではエラーが出力されない(ステータスで確認)  
  console.error(e);
});

`````


allSettledは全ての処理を実行するが完了した非同期処理が成功したか失敗したかはわからない

allの場合はrejectが呼ばれた場合はcatchに処理が移る

````js
function sleep(val) {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      console.log(val++);
      // reject に変更
      reject(val);
    }, val * 500);
  });
}


Promise.all([sleep(2), sleep(3), sleep(4)])
  .then(function(data){
  console.log(data);
}).catch(function(e){
  // この場合catchの処理にエラーの表示が出る
  // allSettleではエラーが出力されない(ステータスで確認)  
  console.error(e);
});

````


今日はここまで！

#参考にさせて頂いた記事

* [【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)
* [Let'sプログラミング JavaScript入門](https://www.javadrive.jp/javascript/)