JavaScriptで実現するスリープ処理:初心者から上級者まで役立つ完全ガイド
JavaScriptにおける「スリープ」処理は、特定の時間だけプログラムの実行を一時停止する方法です。この記事では、JavaScriptでスリープ処理を実装するさまざまな方法を、初心者から上級者まで理解できるように解説します。
スリープ機能は、ウェブアプリケーションでの非同期処理、アニメーション、あるいはユーザーインターフェイスの改善に役立ちます。しかし、JavaScriptには他の多くのプログラミング言語と異なり、ネイティブのスリープ関数が存在しません。そのため、異なるテクニックを駆使して実現する必要があります。
Promiseを使ったスリープ関数の実装
JavaScriptでスリープ機能を実現する最も一般的な方法は、Promiseを使うことです。Promiseは非同期処理の結果を表すオブジェクトであり、これを利用して時間の経過を模倣することができます。
以下の例では、sleep
関数を定義しています。この関数は、引数としてミリ秒単位の時間を受け取り、指定された時間が経過するまで処理を一時停止します。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 |
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function main() { console.log('処理を開始します...'); await sleep(2000); // 2秒待つ console.log('2秒経過しました!'); } main(); |
出力結果
処理を開始します...
2秒経過しました!
setTimeoutを活用した別のアプローチ
もう一つの方法は、setTimeout
関数を直接使うことです。setTimeout
は、指定された時間が経過した後に関数を一度だけ実行するために使用されます。この関数を使って、スリープ処理を実現する小さなトリックを見てみましょう。
ただし、この方法はsleep
関数を使ったPromiseの例とは異なり、コードの実行を「ブロック」しません。その代わりに、指定された時間が経過した後に実行されるコールバック関数内で次の処理を記述する必要があります。
ソースコード例
1 2 3 4 5 6 7 8 9 10 |
function sleep(ms, callback) { setTimeout(callback, ms); } function displayMessage() { console.log('3秒経過しました!'); } console.log('処理を開始します...'); sleep(3000, displayMessage); |
出力結果
処理を開始します...
3秒経過しました!
Promise.allを使用した複数のスリープ処理の同時実行
複数の非同期処理を並行して実行し、すべての処理が完了するのを待つには、Promise.all
メソッドが非常に便利です。
この方法を利用すると、複数のスリープ処理を同時に開始し、すべてのスリープ処理が終了した後に次の処理を進めることができます。例えば、異なるタイミングで複数のAPIリクエストを送り、すべてのリクエストのレスポンスを待ってから処理を進めたい場合などに有効です。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function main() { console.log('処理を開始します...'); await Promise.all([ sleep(2000), sleep(3000), sleep(1000) ]); console.log('すべてのスリープ処理が終了しました!'); } main(); |
出力結果
処理を開始します...
すべてのスリープ処理が終了しました!
高度なスリープ処理テクニック
より高度な使用例として、スリープ処理を利用してリトライロジックを実装する方法があります。
例えば、ある外部APIへのリクエストが失敗したとき、すぐには失敗とせずに、短いスリープ処理の後に再度リクエストを試みるという処理です。この方法により、一時的なネットワークの問題やサーバーの過負荷が原因で発生したエラーを効果的に回避することが可能になります。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
async function retryRequest(url, attempts, delay) { for (let i = 0; i < attempts; i++) { try { const response = await fetch(url); if (response.ok) return response; // 成功したレスポンスを返す // レスポンスが失敗した場合は、指定された時間だけ待つ } catch (error) { console.log(`Attempt ${i + 1} failed, retrying...`); // 最後の試行でなければ待機 if (i < attempts - 1) await new Promise(resolve => setTimeout(resolve, delay)); } } throw new Error('All attempts failed'); } // 使用例 retryRequest('https://example.com', 3, 1000).then(response => console.log('Success:', response)).catch(error => console.error('Error:', error)); |
出力結果
Attempt 1 failed, retrying...
Success: [Responseオブジェクト]
スリープ処理を利用したアニメーション制御
スリープ処理は、アニメーション制御にも利用されます。
アニメーションの各フレーム間に短いスリープを挟むことで、滑らかなアニメーションを実現できます。この手法は、ゲーム開発やウェブアニメーションでよく使用されます。
ソースコード例
1 2 3 4 5 6 7 8 9 10 |
async function animateElement(element, duration) { const start = performance.now(); while (performance.now() - start < duration) { element.style.transform = `translateX(${(performance.now() - start) / duration * 100}px)`; // 次のフレームまで待機 await new Promise(resolve => requestAnimationFrame(resolve)); } } // 使用例 // HTML要素の移動アニメーション const element = document.getElementById('animateMe'); animateElement(element, 2000); |
出力結果
Element smoothly moves 100px over 2 seconds.
KindleUnlimited会員であれば、全ての本をご覧頂けます。 アロー関数と便利な関数を理解すれば、JavaScriptの世界が変わる
まとめ
JavaScriptでスリープ処理を実装する方法は、非同期プログラミングの基本であり、多くの実用的なシナリオに応用できます。
今回紹介したPromiseとasync/awaitを用いたスリープ処理、イベントループの理解、リトライロジックの実装、アニメーション制御といったテクニックは、JavaScriptの非同期処理をより深く理解し、効果的に活用するための基礎を提供します。
最後まで読んで頂き、ありがとうございました。少しでもお役にたてたなら幸いです!