JavaScript コールバック地獄とは

Photo by James Lee on Unsplash プログラミング
Photo by James Lee on Unsplash

こんにちは、コンスキです。

今回はJavaScriptのについてまとめてみました。

JavaScriptのコールバック関数とは

コールバック地獄のコールバックとは、JavaScriptのコールバック関数のことを指しています。

いきなりコールバック地獄の説明をすることは難しいので、まずはコールバック関数について説明しますね。

コールバック(callback)は日本語では「呼び戻し」のように訳されます。

普段呼び戻しという言葉を使うことは滅多にないと思いますが、「呼び戻し=呼ぶ+戻す」でですから、「前にもなんか呼んだけど、またそいつを呼んで来る」的な意味があることはなんとなくわかります。

JavaScriptのコールバック関数も、ある処理を行っていてその処理が終わったときに呼んでくる(実行する)関数のことを指しています。

ここからは具体的なコールバック関数の例について話していきます。

通常、JavaScripでは書かれたコードの上から下のコードまで、順番にコードが実行されていきます。

例えば次のようなコードを書いてみます。

console.log('A');
console.log('B');
console.log('C');

すると実行結果は、次のようになります。

A
B
C

この例は上から下へと順番に実行されているので直感的に理解できると思います。

では、次のような場合はどのような実行結果になるでしょうか。

console.log('A');
setTimeout(function () {
  console.log('B');
}, 1000);
console.log('C');

ぱっと見た感じこの場合も、「A > B > C」の順番で実行されそうですが、実際の実行結果は次のようになります。

A
C
B

「B」と「C」がコードで書かれた順番とは異なって表示されているのがわかります。

このような順番になってしまう原因は、「setTimeout」という名前の関数が使われていることです。

setTimeout関数は、関数の実行を指定した秒数だけ遅らせることができる関数です。

この関数は、

setTimeout(遅らせて実行したい関数、遅らせる秒数(ミリ秒));

という感じで使うことができます。

第2引数として渡すのは、何ミリ秒遅らせて関数を実行するかという値です。

ちなみに、1ミリ秒は1000分の1秒と同じです

そして、第1引数として渡す「遅らせて実行したい関数」がこの例におけるコールバック関数です。

コールバック地獄とは

関数の実行を遅らせる事ができるsetTimeout関数を使って、つぎのことができるコードを書いてみましょう。

1.「こんにちは。」と表示する

 ↓1秒後

2.「コンスキです。」と表示する

 ↓2秒後

3.「お元気ですか?」と表示する

まず、1番目の工程である「こんにちは。」の表示は、setTimeout関数を使わずに次のよう書くことができます。

console.log('こんにちは。');

そして、2つ目の工程は、1番目の工程から1秒後に実行したいのでsetTimeout関数を使うことになります。

1番目の工程のコードも含めて書くと、

console.log('こんにちは。');
setTimeout(function () {
  console.log('コンスキです。');
}, 1000);

のようになります。

3番目の工程では、さらに2秒経過してから「お元気ですか?」と表示したいです。そうするには、つぎのコードを書きます。

console.log('こんにちは。');
setTimeout(function () {
  console.log('コンスキです。');
  setTimeout(function () {
    console.log('お元気ですか?');  
  }, 2000);
}, 1000);

setTimeout関数を2回使ったら急に複雑になった気がしませんか?

このコードが複雑に見えるのは1回目のsetTimeout関数の中で2回目のsetTimeout関数が使われているためです。

そのことからわかるように2回以上関数を遅らせる場合には、setTimeout関数を重ねていく必要ができていきます。

つまりsetTimeout関数の入れ子状態になってしまいます。

試しに1~3までの工程を3回繰り返したらコードはどうなるのでしょうか。

console.log('こんにちは。');
setTimeout(function () {
  console.log('コンスキです。');
  setTimeout(function () {
    console.log('お元気ですか?'); 
    console.log('こんにちは。');
    setTimeout(function () {
      console.log('コンスキです。');
      setTimeout(function () {
        console.log('お元気ですか?');
        console.log('こんにちは。');
        setTimeout(function () {
          console.log('コンスキです。');
          setTimeout(function () {
            console.log('お元気ですか?');
          }, 2000);
        } ,1000);
      }, 2000);
    } ,1000);
  }, 2000);
}, 1000);

複雑なコードになってしまいました。

コールバック関数とそれに対応するミリ秒数が離れすぎて、どれとどれが対応しているのか非常にわかりづらい状態です。

この状態はコールバック地獄と呼ばれています。

たしかにJavaScript初心者の私にとっては間違いなく地獄のような見た目です。

おわりに

この記事を読んでくださった方が、コールバック地獄についてすこしでもわかったことがあればうれしいです。

コールバック地獄に関してわかった方が次に考えるのは、今度はそれをどうやって回避するかだと思います。

コールバック関数の回避方法に関しても、今度まとめようと思っているので、興味があればぜひそちらも見てみてください。

コメント

タイトルとURLをコピーしました