概要
JavaScriptを学習、理解を深めるため「JavaScript Primer 迷わないための入門書」を読み、
理解した内容等を記載していく。
「【JavaScript】JavaScript入門一覧」に他の記事をまとめています。
この記事で理解できること
- 同期処理と非同期処理について
- 非同期処理における例外発生時の挙動
多くのプログラミング言語にはコードの評価の方法として
「同期処理(sync)」「非同期処理(async)」という大きな分類がある。
同期処理
- コードを上から順番に処理する(処理1 -> 処理2 -> 処理3...)
- 一つの処理が終わるまで次の処理は行われない。
// 同期的な処理
console.log("処理1");
console.log("処理2");
console.log("処理3");
// => 処理1
// => 処理2
// => 処理3
JavaScriptにおける同期的処理の懸念点
- JavaScriptは基本的にブラウザのメインスレッド(UIスレッドとも呼ばれる)で処理が実行される。
- メインスレッドは
表示の更新
といったUIに関する処理
などを行なっている。 - その為、メインスレッドが何らかの処理で専有されると、表示がフリーズしたかのような現象が起こる。
※以下のサンプルコードの内容を「index.html」のようなファイル名で保存し、ブラウザで開いてみてください。
※ボタン押下前はホバー時の色の変化が確認が可能ですが、ボタン押下後、3秒間フリーズしたかのような状態になります。
サンプルコード
<html>
<style>
button {
padding: 25px;
border: none;
background: #e5b6e2;
}
button:hover {
background: #dec8dd;
}
</style>
<body>
<button type="button" onclick="block()">ボタン</button>
<script>
// ボタンをクリックした際に呼び出される関数
function block() {
console.log("clickButton");
blockFunc(3000);
}
// 処理を指定時間ブロックする処理
function blockFunc(time) {
const startTime = Date.now();
while (true) {
const diffTime = Date.now() - startTime;
if (diffTime >= time) {
return;
}
}
}
</script>
</body>
</html>
非同期処理
- 同期処理とは異なり、
一つの処理が終わるのを待たずに
次の処理も実行する。 - つまり、非同期処理では
同時に実行している処理
が複数ある。
// 非同期処理の代表的な関数、setTimeout関数を使用する
function asyncFunc() {
console.log('処理1を始めます');
// 仮想的に処理1を5秒かかることにする
setTimeout(() => {
console.log('処理1が終わりました');
}, 5000);
// 並行して処理2を開始
console.log('処理2を始めます');
// 仮想的に処理2を3秒かかることにする
setTimeout(() => {
console.log('処理2が終わりました');
}, 3000);
}
asyncFunc();
// => 処理1を始めます
// => 処理2を始めます
// ...3秒後
// => 処理2が終わりました
// その2秒後(計5秒後)
// => 処理1が終わりました
上記が同期的処理であった場合は、以下のように上から順に処理が行われていたはず。
// ...省略
asyncFunc();
// => 処理1を始めます
// => 処理1が終わりました
// => 処理2を始めます
// => 処理2が終わりました
非同期処理と例外処理
- 非同期処理では、
try...catch構文
を使っても非同期的に発生した例外
をキャッチできない。 - また、非同期処理の外からは
非同期処理の中で例外が発生したかがわからない
。 - そのため、非同期処理の中で例外が発生したことを
非同期処理の外へ伝える
方法が必要。
// 同期処理と例外処理
function syncErrorFunc() {
try {
console.log("同期処理を開始します");
console.log("処理1");
console.log("処理2");
throw new Error("同期処理中にエラーが発生しました");
} catch(error) {
console.log(error.message);
}
}
syncErrorFunc();
// => 同期処理を開始します
// => 処理1
// => 処理2
// => 同期処理中にエラーが発生しました(キャッチできている)
// 非同期処理と例外処理
function asyncErrorFunc() {
try {
console.log("非同期処理を開始します");
console.log("処理1");
console.log("処理2");
// 非同期処理を仮定
setTimeout(() => {
throw new Error("非同期処理中にエラーが発生しました");
}, 1000);
} catch (error) {
// 非同期エラーはキャッチできないため、この行は実行されない
console.log(error.message);
}
}
asyncErrorFunc();
// => 非同期処理を開始します
// => 処理1
// => 処理2
// ...
// => Uncaught Error: 非同期的処理中にエラーが発生しました(キャッチできていない)
以降の関連記事②③④では主要な非同期処理および例外の扱い方として
② コールバックを用いた非同期処理
③ Promise
④ Async Function
について記載する。