JavaScriptの非同期イベント処理の書き方と注意点
生徒
「JavaScriptでボタンをクリックしたときに少し時間がかかる処理をしたい場合、どう書けばいいですか?」
先生
「その場合は非同期処理を使います。JavaScriptではsetTimeoutやPromise、async/awaitを使って処理を遅らせたり、順番を管理できます。」
生徒
「非同期って何ですか?」
先生
「非同期とは、処理が終わるのを待たずに次の処理を進められる仕組みです。例えばボタンを押したあと、サーバーからデータを取得する間も他の操作ができるようになります。」
1. setTimeoutを使った非同期イベント処理
setTimeoutは指定した時間のあとに処理を実行する非同期関数です。ボタンをクリックして一定時間後にメッセージを表示する例を見てみましょう。
const button = document.getElementById("myButton");
button.addEventListener("click", () => {
console.log("クリックされました。処理を待っています...");
setTimeout(() => {
console.log("1秒後にこのメッセージが表示されます");
}, 1000);
});
ここでは1秒後にメッセージが表示されますが、その間に他の処理も実行可能です。
2. Promiseを使った非同期処理
Promiseは非同期処理の結果を表すオブジェクトです。成功時はresolve、失敗時はrejectを呼び出します。
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const data = { name: "太郎" };
resolve(data);
}, 1000);
});
}
const button = document.getElementById("fetchButton");
button.addEventListener("click", () => {
fetchData().then((data) => {
console.log("取得したデータ:", data);
}).catch((error) => {
console.error("エラー:", error);
});
});
Promiseを使うことで、非同期処理の結果を受け取るタイミングを簡単に制御できます。
3. async/awaitを使った非同期処理
async/awaitを使うと、非同期処理を同期処理のように書けます。コードの見通しが良くなり、初心者にも理解しやすいです。
async function handleClick() {
console.log("データ取得中...");
try {
const data = await fetchData();
console.log("取得したデータ:", data);
} catch (error) {
console.error("エラー:", error);
}
}
const button = document.getElementById("fetchButton");
button.addEventListener("click", handleClick);
awaitを使うとPromiseの処理が完了するまで待つことができます。
4. 非同期イベント処理の注意点
- 非同期処理は順序が予測しにくくなることがあります。依存関係がある処理はPromiseチェーンや
async/awaitで順序を制御しましょう。 - 複数の非同期処理を同時に実行すると、思わぬタイミングで処理が終わることがあります。
Promise.allを使うと複数のPromiseの完了を待つことができます。 - 非同期イベントで例外が発生した場合、try/catchや
catchでエラー処理を必ず行いましょう。 - メモリリーク対策として、不要になったイベントリスナーは削除することも忘れないでください。
これらの注意点を意識することで、非同期イベント処理を安全に使うことができます。
5. Promise.allで複数の非同期処理をまとめる
複数の非同期処理を同時に実行し、すべての処理が完了してから次の処理を行いたい場合はPromise.allを使います。これにより、複数の結果をまとめて扱うことができるため、効率的な処理が可能になります。
function task1() {
return new Promise((resolve) => {
setTimeout(() => resolve("処理1完了"), 1000);
});
}
function task2() {
return new Promise((resolve) => {
setTimeout(() => resolve("処理2完了"), 1500);
});
}
Promise.all([task1(), task2()]).then((results) => {
console.log(results);
});
["処理1完了", "処理2完了"]
このように複数の非同期処理をまとめて扱うことで、コードを整理しやすくなります。
6. 非同期処理とイベントの組み合わせ
非同期処理はイベントと組み合わせることで、より実用的な動きを実現できます。例えばボタンをクリックしたときにデータを取得し、その結果を画面に表示する処理などです。
const button = document.getElementById("loadBtn");
button.addEventListener("click", async () => {
console.log("データを取得しています...");
const data = await fetchData();
console.log("取得完了:", data);
});
クリック後にデータが表示される
このようにイベントと非同期処理を組み合わせることで、ユーザー操作に応じた柔軟な処理が可能になります。
7. 非同期処理のデバッグと確認方法
非同期処理は順序が分かりにくいため、デバッグが難しくなることがあります。そのためconsole.logを使って処理の流れを確認することが重要です。またブラウザの開発者ツールを使うことで、実行タイミングを確認することもできます。
console.log("処理開始");
setTimeout(() => {
console.log("非同期処理完了");
}, 1000);
console.log("次の処理へ進む");
処理開始
次の処理へ進む
非同期処理完了
このようにログを確認することで、非同期処理の流れを理解しやすくなります。初心者の方は必ず動きを確認しながら進めることが大切です。