case
以下の順番でコンソールに出力したいができない。
1. fn a done
2. task1 done
3. fn b done
function a() {
setTimeout(function task1() {
console.log('task1 done');
});
console.log('fn a done');
}
function b() {
console.log('fn b done');
}
a();
b();
//出力結果
>>> fn a done
>>> fn b done
>>> task1 done
なぜできないのか?
- 関数aに登録されているsetTimeoutは非同期処理となるため、タスクキューに登録される。
- 関数aコンテキストが終了後にコールスタックに関数bが登録される。
- よってコールスタックに登録されている、関数a内の
fn a done
と関数bのfn b done
が実行されてからタスクキューからコールスタックに登録される。すなわち最後に出力されることになる。 - ※ちなみに、setTimeoutの第二引数に時間を設定していないが、非同期処理となるため、自動的にコールスタック後に出力されることになる。
ソリューション
- 関数aにsetTimeoutのtask1関数ないで関数bを登録することで解決できる。
function a() {
setTimeout(function task1() {
console.log('task1 done');
b();
});
console.log('fn a done');
}
function b() {
console.log('fn b done');
}
a();
>>> fn a done
>>> task1 done
>>> fn b done
tips
このような処理をすることで、特定の非同期処理の後に任意の処理を追加することができる。