JavaScript Tips | 基本・共通ユーティリティ:汎用 – 遅延実行

JavaScript JavaScript
スポンサーリンク

「遅延実行」とは何をしたいテクニックか

「遅延実行」は、その名の通り
「今すぐではなく、少し時間をおいてから処理を実行する」ためのテクニックです。

例えば、次のような場面をイメージしてください。

ユーザーがボタンを押してから 1 秒後にメッセージを出したい。
画面描画が落ち着いてから重い処理を走らせたい。
連続で呼ばれる処理を、少し遅らせてまとめて実行したい(デバウンスの土台)。

こういうときに、「遅延して実行する仕組み」をユーティリティとして持っておくと、
コードの見通しが良くなり、同じパターンを何度もきれいに再利用できます。


JavaScript の基本的な遅延実行:setTimeout

JavaScript で「一定時間後に処理を実行する」基本の仕組みは setTimeout です。

setTimeout(() => {
  console.log("1秒後に実行されました");
}, 1000); // 1000ミリ秒 = 1秒
JavaScript

このコードは、「1秒後にこの関数を実行してね」という予約をしています。
setTimeout 自体はすぐに返り、指定した時間が経ったあとでコールバックが呼ばれます。

ポイントは、「今すぐ実行する」のではなく「後で実行するように登録する」ことです。
これが「遅延実行」の一番シンプルな形です。


ユーティリティとしての遅延実行関数 delay

毎回 setTimeout を直接書いてもいいのですが、
業務コードでは「関数をラップして“遅れて実行される版”を返す」ユーティリティにしておくと、とても使いやすくなります。

シンプルな delay 実装

まずは基本形から。

function delay(fn, ms) {
  return function delayed(...args) {
    setTimeout(() => {
      fn(...args);
    }, ms);
  };
}
JavaScript

この delay は、「元の関数 fn を、ms ミリ秒遅れて実行する関数」に変換してくれます。

使い方はこうです。

function greet(name) {
  console.log(`こんにちは、${name} さん`);
}

const greetLater = delay(greet, 1000);

greetLater("太郎"); // 1秒後に「こんにちは、太郎 さん」と表示される
JavaScript

ここで重要なのは、「greetLater を呼んだ瞬間には何も起きず、“予約だけされる”」という点です。
実際の処理は、指定した時間が経ってから実行されます。


this を保ったまま遅延実行する

クラスやオブジェクトのメソッドを遅延実行したいときは、this を正しく保つことが大事です。
そのために applycall を使います。

function delayWithThis(fn, ms) {
  return function delayed(...args) {
    const context = this;
    setTimeout(() => {
      fn.apply(context, args);
    }, ms);
  };
}
JavaScript

使い方の例です。

const user = {
  name: "山田",
  sayHello() {
    console.log(`こんにちは、${this.name} です`);
  },
};

user.sayHelloLater = delayWithThis(user.sayHello, 500);

user.sayHelloLater(); // 0.5秒後に「こんにちは、山田 です」
JavaScript

ここでの深掘りポイントは、「this を失わないように fn.apply(context, args) としている」ことです。
単に fn(...args) と書くと、thisundefined になってしまい、メソッド内で this.name が使えなくなります。


Promise ベースの遅延実行 delayAsync

「一定時間待ってから次の処理をしたい」というとき、
async/await と組み合わせて使える Promise 版の遅延ユーティリティもよく使います。

function delayAsync(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}
JavaScript

使い方はこうです。

async function main() {
  console.log("開始");
  await delayAsync(1000); // 1秒待つ
  console.log("1秒後に実行");
}

main();
JavaScript

ここでの重要ポイントは、「await delayAsync(ms) と書くことで、“時間待ち”を普通の処理のように書ける」ことです。
これを使うと、例えば「API を叩いてから 500ms 待ってローディングを消す」といった処理が、とても読みやすく書けます。


遅延実行ユーティリティと debounce / throttle へのつながり

遅延実行は、それ単体でも便利ですが、
「高頻度イベントを制御するテクニック」の土台にもなります。

入力が止まってから 300ms 後にだけ検索処理を走らせる(debounce)
スクロール中、一定間隔ごとにだけ処理を走らせる(throttle)

こういったユーティリティは、内部で setTimeout を使って「遅延して実行する」仕組みを組み立てています。

まずは今回のようなシンプルな delaydelayAsync を自分で書いてみて、
「処理を“今すぐ”ではなく“あとで”に回す感覚」をつかむと、
その先の debounce / throttle も理解しやすくなります。


実務での具体的な利用イメージ

例えば、ボタンを押したあとに「処理中…」と表示し、
1 秒後に「完了しました」と表示したいケースを考えてみます。

const showDoneLater = delay(() => {
  console.log("完了しました");
}, 1000);

function onClick() {
  console.log("処理中…");
  showDoneLater();
}

onClick();
// すぐに「処理中…」
// 1秒後に「完了しました」
JavaScript

あるいは、async/await を使って「待つ」ことを明示的に書くこともできます。

async function runTask() {
  console.log("処理開始");
  await delayAsync(1500);
  console.log("1.5秒後に次の処理");
}

runTask();
JavaScript

こうやって、「時間をずらして実行する」という発想をユーティリティとして持っておくと、
アニメーション、ローディング表示、API 呼び出しの間隔調整など、
実務でよく出てくる“ちょっとした時間調整”が、きれいなコードで書けるようになります。

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