(Web関連用語)
https://tcd-theme.com/2021/09/javascript-asynchronousprocess.html
同期処理
同期処理は、上から順番に処理を実行し、一つの処理が終わったら次の処理へ移動する。言い換えると、一つの処理が終わるまで次の処理を行うことができない。
処理1(はじめの処理)→ 処理2(1番目の処理が終わったら実行) → 処理3(2番目の処理が終わったら実行)
同期処理は、プログラムの基本的な考え方であり、処理全体を把握しやすいといったメリットがある。また同時に、プログラムによってはタスク完了までに時間を要するため、ユーザーにとってストレスになる側面もある。
非同期処理
JavaScriptでは、同時に複数の処理を行うことができない代わりに、時間のかかる処理が完了するまでの間、他の処理を進めていくことができる。これを非同期処理と言う。
非同期処理は、書かれているコードとは異なる順番で処理を実行する。
処理1(はじめの処理 → 完了)→ 処理2(時間のかかる処理 → 待機します)→ 処理3(2番目の処理を待っている間に実行 → 完了)→ 処理2(準備完了 → 処理を完了させるよ)
処理に時間がかかるプログラムが含まれている場合には、非同期処理は非常に効率的である。
コールバック関数
非同期処理には「コールバック関数」「Promise」「Async/Await」など、さまざまな方法がある。
その中で「コールバック関数」とは、ある関数の引数として渡される関数のことである。ある関数が一定の処理を終えたら呼び出されるため、コールバック関数と呼ばれている。
setTimeout関数
JavaScriptの代表的な非同期処理のコールバック関数として、setTimeout関数がある。
console.log('1');
setTimeout(() => {
console.log('2')
}, 1000);
console.log('3');
>> 1 → 3 → 2
上記のコードでは、console.log(‘1’) → setTimeout() → console.log(‘3’)の順番に処理が登録される。ここまでは同期処理と同じである。
しかし、setTime関数で登録したコールバック関数は、1000ミリ秒後に処理を実行させるように、非同期的なタイミングで呼び出される。
そのため、setTimeout()よりも後に書かれているconsole.log(‘3’)が先に実行されるということになる。
関数の引数に指定
function getWeather(weather) {
console.log('今日の天気は' + weather);
}
function tellWeather(data) {
let tellSomething = '晴れです';
data(tellSomething);
}
tellWeather(getWeather);
>> 今日の天気は晴れです
一番下のコードを見ると、tellWeather関数の引数にgetWeather関数を指定していることが確認できる。このgetWeatherがコールバック関数に当たる。
tellWeather関数の処理が終えたら、getWeather関数が呼び出される仕組みである。
コールバック関数は、必ずしも関数宣言で書く必要はなく、人によっては無名関数やアロー関数の方が分かりやすい場合もある。
上記の例をアロー関数に書き換えると以下のようになる。
function tellWeather(data) {
let tellSomething = '晴れです';
data(tellSomething);
}
tellWeather(weather => console.log('今日の天気は' + weather));
>> 今日の天気は晴れです
コールバック地獄
コールバック関数は、かんたんなプログラムであれば直感的に理解がしやすいが、複数の非同期処理を行う必要がある場合、把握しづらくなるデメリットがある。
下記の例は、関数の呼び出し時にsample_1()の結果を使ってsample_2()を呼び出し、さらにその結果を使ってsample_3()を呼び出す…のように処理がネストの状態になっている。
function sample_1() { 処理; }
function sample_2() { 処理; }
function sample_3() { 処理; }
function sample_4() { 処理; }
function sample_5() { 処理; }
// 呼び出し
sample_1(function () {
sample_2(function () {
sample_3(function() {
sample_4(function() {
sample_5();
});
});
});
});
このように複数のコールバック関数を連結して、ネストの状態が続いていることをコールバック地獄と呼ぶ。
関数の実行結果を次々と新しいコールバック関数に利用していくことで、ネストが深くなっているのが分かる。
そのため、コールバック関数は複雑なプログラムになるにつれて、どのような処理をしているのか把握しにくくなる点に注意が必要である。