Re: [討論] javascript是共時、多執行緒嗎?

看板Ajax作者 (彷彿曾經一起死過)時間13年前 (2011/11/05 19:29), 編輯推噓3(308)
留言11則, 4人參與, 最新討論串3/11 (看更多)
跟大家分享一下 我對一般常見的browser處理javascript的認知 有錯誤請大家不吝指教 先回答標題好了 就我所知 目前javascript在browser的implementeation中 在一個"window"下中只有一個thread 在這種情況下 你可以說javascript是單一thread 事實上大部分的時候 我們只要以這出發點來考慮問題就足夠了 然而 如果你的頁面中有iframe 他會有另外一個window去維護另一個thread 在同網域下 他甚至可以存取相同的global物件 造成所謂的race condition 在這種狀況下 你可以說javascript 是 multi-thread 我想也是合理的 ======================= 所以說 與其討論javascript到底是不是multi-thread 其實應該討論的問題是 browser的實作方式 首先我們開啟一個頁面 在這個window中會開啟一個thread 處理包括 1.html的parse 2.dispatching of events 3.執行javascript 然後在parse的過程中 如果遇到某些tag像是img, embed, iframe,object 等等 他會開啟另外一個thread去下載,render,或是執行iframe裡面的js等等 這也是為甚麼 我們會看到在load一個網頁 下載圖片是分開的 每張獨立下載 獨立顯示 同時這種作法 也大大加速了我們顯示整個網頁的速度 而這和我們的問題有甚麼關係呢? 在我們前端開發人員的聖經"High Performance Web Sites"中提到 我們應該盡量的把javascript放在網頁的下面 為甚麼呢 因為在同一個window的single thread中 如果遇到<script> html parsing的動作會停下來 直到 1.下載 javascript(如果是外部連結的話) 2.parse 3.執行 三個動作結束後 才會繼續往下 如果這個javascript特別久 那下面網頁就久久不parse,整個page loading就卡在那裏 所以呢 你應該已經猜到 在你load page時 不同<script>間的javascript執行一定是分開 的 只有一段<script>跑完 才有機會繼續往下parse HTML 也才有機會遇到另外一個<script> 然後執行它 而這個部分 我相信每個人都可以直觀的觀察到 這是single thread的感覺 那為甚麼有人會提出這類的問題 我想主要是因為javascript的一些feature如ajax,timer,alert...等等造成困惑 要理解這些困惑 我們要先理解 javascript是怎麼被執行的 以下有兩種狀況會執行js 1.page load時立刻執行的js 2.event handler 第一種我們已經討論過了 很單純的由上往下 一個一個來 第二腫 在js中我們都視為一種callback 當事件引發時 才會執行 在browser對js的處理中 它maintain一個queue叫做 "Dispatch Sequence" 當事件觸發時 會立刻把handler放到裡面(這動作叫作dispatch) 然後根據先來後到的順序執行handler 而在這過程中 當前一個handler沒跑完之前 下一個hander不會被執行 所以說 js依然是single thread timeout,或是ajax callback等等 我們都要視為是一個event 一樣是用這個規則在跑 所以 timeout 5秒不一定會在5秒時跑 ajax callback也不一定會在respose 抵達時馬上 fire 一切都要看 前面的handler執行完了沒 輪到他了沒 (題外話 alert 是個special case, 每個browser不太一樣 , 寫js的人要盡量少用) 那最後回到我們的問題來 那個alert ABCD會不會交叉出現呢 答案是不會 (alert要少用 像是sk1765的test case就 非常好) 相信你已經知道 在timeout中的function A B都是一個event handler(callback) 在執行時 會結束才有可能去執行另一個 所以不會ABCD交叉出現 最後我想說的是 js要看成是 event-driven的東西 用thread去分析 就會陷入把他拆成一行一行看的陷阱 而event-driven 產生的timing issue 對我來說 也是js bug中最難trace的一種 文章寫的有點長 但其實還有很多細節 opera這篇文章寫得非常非常好 有興趣的各位可以參考看看 http://dev.opera.com/articles/view/timing-and-synchronization-in-javascript/ ※ 引述《TonyQ (自立而後立人。)》之銘言: : ※ 引述《ec75413 (無虧/明月幾時有?)》之銘言: : : 在這裡沒找到類似的討論串 網路上中文的也很少 : : 但英文還算不少 : : 所以把這個議題放上來。 : : 不知這個問題已經是老梗了 還是...? : javascript 是同步的 : 也就是不會有兩行 statement 同時執行的 : 但是他可以是多執行續。 : 也就是假設你有一個 funciont 是 : function A(){ : alert("A"); : alert("B"); : } : function B(){ : alert("C"); : alert("D"); : } : 透過 setTimeout / setItnerval , : 是有可能會發生這樣的執行序 : alert("A");//from A : alert("C");//from B : alert("B");//from A : alert("D");//from B : 你把 js 底層的引擎想像成一個 queue , : 有要執行的指令就推進去,引擎會去跑他, : 但同時間他只能處理一個指令。 : 一般當你真的很需要控制執行的順序的時候, : 我們會多加幾個 flag 作為 lock ,或者自己實做queue。 : 但是基本上 javascript 要作到 java 的 synchronized keyword 做的事情, : 是沒有辦法保證一定做的到的,最好盡量避免這麼嚴苛的狀況。:P -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 71.107.60.113

11/06 00:06, , 1F
跟我的觀念差不多 不過我本來以為同一個頁面放兩個iframe
11/06 00:06, 1F

11/06 00:08, , 2F
裡面各自alert 會在同一時間在browser上同時出現兩個dialog
11/06 00:08, 2F

11/06 00:10, , 3F
結果也沒有 所以alert這個function 他還是同一時間不會並行
11/06 00:10, 3F

11/06 00:13, , 4F
一般的script應該就是像你說的 兩個iframe個跑各的
11/06 00:13, 4F

11/06 03:00, , 5F
感謝,對原理完全不懂,第一次就觀念釐清真是再好不過了:)
11/06 03:00, 5F

11/06 03:41, , 6F
http://jsfiddle.net/3gH3J/ opera同時 chrome照順序
11/06 03:41, 6F

11/06 03:41, , 7F
不過是我的測試結果啦...
11/06 03:41, 7F

11/06 09:55, , 8F
opera可以同時一堆alert嗎? 這應該是multi-thread的好例子
11/06 09:55, 8F

11/06 16:28, , 9F
我把alert的dialog移動一下,看見另外一個alert
11/06 16:28, 9F

11/06 16:28, , 10F
所以應該是同時吧XD
11/06 16:28, 10F

11/06 16:33, , 11F
咦 沒注意到有另外發文XD
11/06 16:33, 11F
文章代碼(AID): #1EjHu8Bn (Ajax)
討論串 (同標題文章)
文章代碼(AID): #1EjHu8Bn (Ajax)