きっかけ
setTimeout使ったフェールセーフな実装をしていたのだが、デバッグでハマってしまった。。。
1時間位悩んでしまったので、晒す。
ネタソース
お題となるソース。
実際はもっと複雑だけど、簡略化するとこんな感じ。
※本当はTypeScriptでソース書いてるんで、JavaScriptはなんとなく分かる程度です。。。
<html> <head> </head> <body> <script language="JavaScript"> var test = function () { var timer = function () { console.log("timer fire!"); }; console.log("process start"); setTimeout(timer, 1000); console.log("process end"); }; </script> <button onclick="test();">execute</button> </body> </html>
やりたきこととしては、 console.log("process end");
の処理に時間がかかったら、 console.log("timer fire!");
が実行されるよね?を確認したかった。
そのために、 console.log("process end");
のところで、ブレークポイントを張って、処理を止めて確認した。
検証環境
- Google Chrome 61.0.3163.100
- Firefox 56.0
どっちも同じ結果。
実行結果
process start
が表示され、 console.log("process end");
でブレークポイント張ってるんで処理がとまる。
しかし、待てど暮らせど setTimeout(timer, 1000);
は発火しない。
理由
理由は簡単。JavaScriptはシングルスレッドなので、ブレークポイントで処理を止めると、全て止まる。
まるで、DIOのザ・ワールドだね!全ての時が止まるなんて!
自分の理解では、setTimeoutはJavaのスレッドみたいに並列処理してるんやろな~みたいに思っていた。。。
JavaScriptは、シングルスレッドだということは知っていたけど、こいうことなんですね。。。
冷静に考えれば、たしかにそうだねって分かるけど、業務中だとあんまり頭が回ってないのかも知れない。