promptのうしろでタイマハンドラは呼んでもらえる
はてなブックマーク - COLLECTION & COPY / 2007年09月06日
setTimeout/setInterval、実装、図解、←すばらしい!!、タイマー+キュー、←経験的に暗黙にわかっていたことがはっきりする、←prompt/alertで抜けるということはキューは複数ありそう
ほんとだ。すげえ。jsはシングルスレッド、っていうのが厳密には正しくない理解なのがわかる。prompt出した後出したやつはok押されるまでsleepしてるからほかのイベントがハンドルされてるってことなんだろうけどどうなってるんだろう。"ok押されたイベント"はjsを実行してるスレッドがハンドルしないと処理できないはずだからキューが二つあると実装大変そうな気がするけどどうなってるのかな.....プリエンプトできるようになっているように思える。
違った。プリエンプトはできない。どうなってるのかわかんないけどスレッドが二つある。二つしかない。
<script type="text/javascript" charset="utf-8"> // <![CDATA[ window.onload = function () { window.document.body.onclick = function () { var i = 0; setInterval( function () { i++; confirm(i); }, 1000); var n = confirm("hi"); console.log(n); } } // ]]> </script>
を実行してクリックすると"hi"と"1"だけが出てくる。"2"は出てこない。"1"をconfirmしてあげると"2"がでてくる。これFirefoxのときだけだ。IEだと想像通り"hi"が出るだけで"1"は出てこない。
ということはどういうことだ....?
タイムアウトを実行してるスレッドと、イベントをハンドリングしているスレッドと少なくとも二つがあるってことになるけど、そうすると今度はじゃあどこでイベント処理とタイムアウト処理の排他制御してるのかがわかんなくなる。
// <![CDATA[ window.onload = function () { window.document.body.onclick = function () { setInterval( function () { confirm( "1000ms"); }, 1000); setInterval( function () { confirm( "500ms"); }, 500); var n = confirm("hi"); console.log(n); } } // ]]>
こうしたら"hi", "500ms", "1000ms" だけでてきた。前のIntervalTimer処理が終わってないときには次のintervalTimerイベントは抑制されるようになってる(なってないとコンシステンシーをとらないOOOになっちゃう)ので何回も出たりはしない。
promptを呼ぶと、そのイベント処理はpendingして、次のイベントを実行することができるけど、pendingしてるイベントと同種のイベントは実行できない、とかかな.....
// <![CDATA[ window.onload = function () { window.document.body.onclick = function () { for ( i = 1; i <= 20; i++ ) { var t = 200; ( function (timeout) { setInterval( function () { confirm( timeout + "ms"); }, timeout ); } ) (i * t); } var n = confirm("hi"); console.log(n); } } // ]]>
にしてみたら20こダイアログが出てくるけどfirefox.exeの持ってるスレッドが激増したりはしないので、書いたエントリが大きくはずしてたりはしなそうなきになれたところで保留。