駆け出しのエンジニア日記

プログラミング言語勉強中の奮闘日記

Promise

「Promise」を理解する前に重要な概念である「同期処理・非同期処理」と、「コールバック」についてまとめます。

同期処理

プログラムを上から下へ順番に一つずつ処理していくものになります。

処理1
処理2
処理3 続く・・・

しかし、途中で時間の掛かる処理(サーバーからデータを取得するような)があるとそれ以降の処理が止まってしまい、通信が完了するまで待つ必要があります。(時間がかかります)

それを解決するためにJavaScript非同期処理というものを用意しています。

簡単に書くとこんな感じです。

console.log('サーバーにリクエストを送信');  ・・・1
setTimeout*1
.then*2
.then*3
.then*4
.then*5
.then*6
// .catch(() => {
〜処理〜
// })
//今回はエラーなどは特に起きないのでcatchは不要

上記でネストして書かれていたコードより見やすくなったと思います。

ここで「then」というメソッドがでできました。

最初の引数に成功した時用のコールバック関数を登録できます。

「then」はそれから〜という意味があるので、処理の意味としては背景を赤にし、それからオレンジにし、それから黄色にし〜と続いていく流れになっています。

コメントアウトのところに「catch」とありますが、これは「then」の反対で、失敗した時用のコールバック関数を登録できるものとなります。

 

*1:) => {

console.log('サーバーからレスポンスが来ました!!');  ・・・3
}, 3000);
console.log('ここがファイルの末端');  ・・・2

まず「1」が実行されます。次にsetTimeoutが実行されます。中身は3秒後と設定しているので飛ばされます。そして「2」が実行されます。3秒後に「3」の結果が出力されることになります。

つまり、時間の掛かりそうな処理を実行したあとに結果を待たずにすぐ次の処理を実行できます。

上記ではsetTimeoutの引数にコールバックを設定すれば関数を指定できるようになります。

console.log( ~ )がコールバック関数の中身ということになります。

 

「非同期処理」と「コールバック処理」は組み合わせてよく使われるのですが、記述量が増え、ややこしくなったり見にくくなるというデメリットがあります。

例えば、背景色を1秒ごとに変えたい場合、

setTimeout(() => {
     document.body.style.backgroundColor = 'red';
      setTimeout(() => {
             document.body.style.backgroundColor = 'orange';
             setTimeout(() => {
                  document.body.style.backgroundColor = 'yellow';
                   setTimeout(() => {
                        document.body.style.backgroundColor = 'green';
                        setTimeout(() => {
                            document.body.style.backgroundColor = 'blue';
                            }, 1000);
                     }, 1000);
                }, 1000);
         }, 1000);
}, 1000);

どんどんネストされていき、エラーが起きる可能性が増えます。この状態を「コールバック地獄」と言います。

Promiseはこの問題を解決してくれるものになります。

ここでPromiseには3つの状態があるのを紹介します。

  • 待機 (pending): 初期状態。成功も失敗もしていません。
  • 履行 (fulfilled): 処理が成功して完了したことを意味します。
  • 拒否 (rejected): 処理が失敗したことを意味します。

Promiseオブジェクトの書き方

 new Promise()
//Promiseの中にコールバック関数を記述
new Promise((resolve, reject) => {
})

そして2つのパラメーターを用意します。

2つとも関数であり、成功した時によぶ関数が「resolve」と失敗した時によぶ関数が「reject」です。

 

先ほどコールバック地獄になっていた背景色の記述を、実際にPromiseオブジェクトを作成し、修正してみましょう。

const delayedColorChange = (color, delay) => {
  return new Promise((resolve, reject) => {
       setTimeout(() => {
             document.body.style.backgroundColor = color;
            resolve();
     }, delay);
  })
}

delayedColorChange('red', 1000)
.then(() => delayedColorChange('orange', 1000

*2:) => delayedColorChange('yellow', 1000

*3:) => delayedColorChange('green', 1000

*4:) => delayedColorChange('blue', 1000

*5:) => delayedColorChange('indigo', 1000

*6:) => delayedColorChange('violet', 1000