JavaScript

【JS】連続するsetTimeoutをスッキリさせる【コピペで解消】

こんにちは。
今回はJavaScript(以下JS)で連続でsetTimeout()を実装する時によく陥る「コールバックヘル」を解消する方法を記載します。

なお、コピペで完結させたいので難しい用語の解説は一切抜きにしています。
解説は別の記事で書こうと考えております。

とりあえず、速攻でsetTimeout()をスッキリさせたい、見やすくさせたい!って方はこの記事のコードをコピーすればOKかと思います。

連続でsetTimeout()を使うとどうなる?

実際に記述してみます。

setTimeout(() => {
  console.log('1秒経ちました');
  setTimeout(() => {
    console.log('2秒経ちました');
    setTimeout(() => {
      console.log('3秒経ちました');
      setTimeout(() => {
        console.log('4秒経ちました');
      }, 1000);
    }, 1000);
  }, 1000);
}, 1000);

この記述は1秒ごとに○秒経ちましたとカウントするようにしている記述です。
つまり、
1秒経てば、「1秒経ちました」
2秒経てば、「2秒経ちました」
3秒経てば、「3秒経ちました」....
とコンソールに出てきます。

いかがでしょう?見にくいと感じましたでしょうか?
今回の例だと「console.log('○秒経ちました');」の一文なので割と見やすいですが、この「console.log('○秒経ちました');」の部分に数行にわたる関数が記載されているとどうでしょう?
かなり見にくくなり、「あれ?何秒後に何の記述してるんだっけ?」と言う状況に陥ります。

ちなみに、上記の例のようにsetTimeoutを繰り返し使うことによってコールバックのネストが深くなっていくことを「コールバックヘル」と言います。
コールバックヘルの特徴として、下の画像のように左側に三角形が入るような見え感になります。

さぁコピペはここからだ!

下記のコードをコピペすれば見にくいsetTimeoutのコールバックヘルを解消することができます。
コピー用のソースコードはもう少し下の方に用意しております。

const wait = function (seconds) {
  return new Promise(function (resolve) {
    setTimeout(resolve, seconds * 1000);
  });
};


wait(1)
  .then(() => {
    console.log('1秒経ちました');
    return wait(1);
  })
  .then(() => {
    console.log('2秒経ちました');
    return wait(1);
  })
  .then(() => {
    console.log('3秒経ちました');
    return wait(1);
  })
  .then(() => console.log('4秒経ちました'));

これで先ほどと同じ動作をします。

new Promise, resolve, then,,,,,???となると思いますが、
この記事の目的は「コピペで実装」なのでこれらの説明は割愛します。

コピペする部分は2つに別れます。
まず上部の

const wait = function (seconds) {
  return new Promise(function (resolve) {
    setTimeout(resolve, seconds * 1000);
  });
};

これが秒(時間)をコントロールしている部分となります。
そして下部、

wait(1)
  .then(() => {
    console.log('1秒経ちました');
    return wait(1);
  })
  .then(() => {
    console.log('2秒経ちました');
    return wait(1);
  })
  .then(() => {
    console.log('3秒経ちました');
    return wait(1);
  })
  .then(() => console.log('4秒経ちました'));

ここに待って欲しい「秒」と「動き」の記述をします。

wait()の中に書いている数字が「待って欲しい秒」です。
そしてthenのなかに「動作」を記述します。
thenのなかにreturn wait()で次の挙動まで待って欲しい秒を入れます。

コピペ用ソースコード↓

const wait = function (seconds) {
  return new Promise(function (resolve) {
    setTimeout(resolve, seconds * 1000);
  });
};


wait(○) // 待って欲しい○秒書く
  .then(() => {
   // ▼▼挙動を書く▼▼
     
   // ▲▲挙動を書く▲▲ 
    return wait(○); //待って欲しい○秒書く
  })
  .then(() => {
    // ▼▼挙動を書く▼▼
     
    // ▲▲挙動を書く▲▲ 
    return wait(○); //待って欲しい○秒書く
  })
  .then(() => {
    // ▼▼挙動を書く▼▼
     
    // ▲▲挙動を書く▲▲
    return wait(○); //待って欲しい○秒書く
  })
  .then(() => {
    // ▼▼挙動を書く▼▼
     
    // ▲▲挙動を書く▲▲
  });

今回の例だと4つの挙動ですが、発生させたい挙動数に応じてブロック数を調整してください。

まとめ

いかがでしょうか?
上記のソースだとそれぞれの挙動を書く時にブロックが並列になっているのでコールバックヘルに陥らずに、きれいに書けます。
また「○秒後に,,,」って言うのも挙動を書くブロックのすぐ下にあるので視覚的にわかりやすいですね。


今回は以上となります。
皆さんの理解の手助けとなっていれば幸いです。


▼▼人気の記事▼▼

【経験談】給料を上げたいなら自分に対しての出費を増やそう【自己投資のススメ】

-JavaScript
-, , , , , ,