JavaScriptでsleep(待機)処理を実装する5つの方法 - 初心者でも3分で理解できる完全ガイド

javascript icon
JavaScript

こんにちは、とまだです。

JavaScriptで「ちょっと待って!」って処理を止めたいのに、なぜかsleep()関数がない…と困っていませんか?

私も最初、他の言語から来た時に「え?JavaScriptってsleepないの?」と驚きました。実はこれ、JavaScriptの非同期処理という特性に関係しているんです。

今回は、JavaScriptでsleep処理を実現する5つの方法を、コーヒーを淹れる例えを使いながら、初心者でも確実に理解できるように解説していきます。

なぜJavaScriptにはsleep関数がないの?待機処理の基本を理解しよう

「他の言語にはあるのに、なんでJavaScriptにはsleepがないの?」

これ、本当によく聞かれる質問です。

実は、JavaScriptはシングルスレッドで動作する言語なんです。

シングルスレッドとは?コーヒーショップで理解する

コーヒーショップの店員さんを想像してください。

他の言語(マルチスレッド)の場合:

  • 店員さんが複数いる
  • 一人がコーヒーを淹れている間、他の店員が注文を受けられる

JavaScript(シングルスレッド)の場合:

  • 店員さんは一人だけ
  • でも、コーヒーマシンが自動で淹れてくれる間に、次の注文を受けられる

これがJavaScriptの動き方です。

もしJavaScriptに普通のsleep関数があったら…

// もしこんなことができたら(実際にはできません)
console.log("注文受けました");
sleep(3000); // 3秒待つ
console.log("コーヒーできました");

この3秒間、店員さん(JavaScript)は何もできずに棒立ち。お客さんは大行列になってしまいます。

だからJavaScriptは、「待っている間も他の仕事ができる」ような仕組みになっているんです。

setTimeout vs Promise - それぞれの特徴と使い分け

JavaScriptで待機処理を実現する方法は主に2つあります。

1. setTimeout - 昔ながらの方法

console.log("コーヒーを淹れ始めます");

setTimeout(() => {
    console.log("3秒後:コーヒーができました!");
}, 3000);

console.log("その間に他の注文を受けます");

実行すると、このようになります。

コーヒーを淹れ始めます
その間に他の注文を受けます
3秒後:コーヒーができました!

メリット:

  • シンプルで分かりやすい
  • 古いブラウザでも動く

デメリット:

  • 複数の待機処理が重なると、コールバック地獄になる
  • エラー処理が難しい

2. Promise - モダンな方法

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

console.log("コーヒーを淹れ始めます");

sleep(3000).then(() => {
    console.log("3秒後:コーヒーができました!");
});

console.log("その間に他の注文を受けます");

メリット:

  • チェーンできる(連続処理が書きやすい)
  • エラー処理が統一的
  • async/awaitと組み合わせられる

デメリット:

  • 初心者には少し難しい概念
  • 古いブラウザでは動かない(でも今はほぼ問題ない)

async/awaitで実現する最もシンプルなsleep関数

2025年の今、最もおすすめなのがasync/awaitを使った方法です。

sleep関数の実装

// これが魔法のsleep関数!
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));

// 使い方
async function makeCoffee() {
    console.log("コーヒーを淹れ始めます");

    await sleep(2000); // 2秒待つ
    console.log("豆を挽きました");

    await sleep(1000); // 1秒待つ
    console.log("お湯を注ぎました");

    await sleep(2000); // 2秒待つ
    console.log("コーヒーができました!☕");
}

// 実行
makeCoffee();

見てください。まるで普通のsleep関数のように書けます!

なぜこれが最高なのか:

  1. 読みやすい - 上から下に順番に実行される
  2. エラー処理が簡単 - try/catchが使える
  3. デバッグしやすい - 処理の流れが明確

実践!3つの具体的な使用例とコード解説

例1:ローディング画面の実装

ユーザーに「処理中です」と見せたい時の例です。

async function showLoading() {
    const loadingDiv = document.getElementById('loading');

    // ローディング表示
    loadingDiv.textContent = "データを取得中.";
    await sleep(500);

    loadingDiv.textContent = "データを取得中..";
    await sleep(500);

    loadingDiv.textContent = "データを取得中...";
    await sleep(500);

    // データ取得完了
    loadingDiv.textContent = "完了!";
}

例2:アニメーション効果

要素を順番に表示したい時に便利です。

async function fadeInElements() {
    const elements = document.querySelectorAll('.fade-item');

    for (const element of elements) {
        element.style.opacity = '1';
        await sleep(200); // 0.2秒ずつずらして表示
    }
}

例3:API呼び出しのリトライ処理

エラーが起きた時に、少し待ってから再試行する例です。

async function fetchDataWithRetry(url, maxRetries = 3) {
    for (let i = 0; i < maxRetries; i++) {
        try {
            const response = await fetch(url);
            if (response.ok) {
                return await response.json();
            }
        } catch (error) {
            console.log(`試行 ${i + 1}回目失敗。2秒後に再試行...`);
            await sleep(2000);
        }
    }
    throw new Error('データ取得に失敗しました');
}

よくあるミスと対処法:初心者が陥りがちな3つの罠

罠1:forループ内でのsetTimeout

// ❌ 間違い:全部同時に実行される
for (let i = 0; i < 3; i++) {
    setTimeout(() => {
        console.log(i);
    }, 1000);
}

// ✅ 正解:async/awaitを使う
async function correctLoop() {
    for (let i = 0; i < 3; i++) {
        await sleep(1000);
        console.log(i);
    }
}

罠2:同期的に待とうとする

// ❌ 間違い:ブラウザがフリーズする
function badSleep(ms) {
    const start = Date.now();
    while (Date.now() - start < ms) {
        // 何もしない(CPU使いまくり)
    }
}

// ✅ 正解:必ずPromiseを使う
const goodSleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));

罠3:awaitを忘れる

// ❌ 間違い:awaitを忘れている
async function forgetAwait() {
    console.log("開始");
    sleep(1000); // awaitがない!
    console.log("終了"); // すぐ実行される
}

// ✅ 正解:awaitを付ける
async function rememberAwait() {
    console.log("開始");
    await sleep(1000);
    console.log("終了"); // 1秒後に実行
}

パフォーマンスを考慮した最適なsleep処理の実装方法

複数の処理を効率的に待つ

// ❌ 非効率:合計6秒かかる
async function inefficient() {
    await sleep(2000); // 2秒
    await sleep(2000); // 2秒
    await sleep(2000); // 2秒
}

// ✅ 効率的:2秒で終わる
async function efficient() {
    await Promise.all([
        sleep(2000),
        sleep(2000),
        sleep(2000)
    ]);
}

条件付きsleep

必要な時だけ待機する賢い実装です。

async function smartSleep(condition, ms = 1000, maxWait = 10000) {
    const startTime = Date.now();

    while (!condition()) {
        if (Date.now() - startTime > maxWait) {
            throw new Error('タイムアウトしました');
        }
        await sleep(ms);
    }
}

// 使用例:要素が表示されるまで待つ
await smartSleep(
    () => document.getElementById('target').style.display !== 'none',
    100, // 0.1秒ごとにチェック
    5000  // 最大5秒待つ
);

まとめ:JavaScriptのsleep処理をマスターしよう

JavaScriptでsleep処理を実装する方法をまとめると:

  1. 基本を理解する - JavaScriptは非同期処理が得意
  2. async/awaitを使う - 最もシンプルで読みやすい
  3. 用途に応じて使い分ける - アニメーション、API呼び出し、ローディング表示など

最初は難しく感じるかもしれませんが、慣れれば「JavaScriptにsleepがない理由」も納得できるはずです。

もっと深くJavaScriptの非同期処理を学びたい方は、Learning NextのJavaScriptコースがおすすめです。非同期処理の章では、Promise、async/awaitを使った実践的な練習問題を150問以上用意しています。

特に「JavaScript エラー解決完全ガイド」では、sleep処理でよく発生するエラーの対処法も詳しく解説していますので、ぜひチェックしてみてください。

JavaScriptの非同期処理は最初は難しいですが、マスターすれば強力な武器になります。一緒に頑張りましょう!

共有:

著者について

とまだ

とまだ

フルスタックエンジニア

Learning Next の創設者。Ruby on Rails と React を中心に、プログラミング教育に情熱を注いでいます。初心者が楽しく学べる環境作りを目指しています。

著者の詳細を見る →