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

看板Ajax作者 (彷彿曾經一起死過)時間13年前 (2011/11/06 09:49), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串4/11 (看更多)
alert在不同thread下(iframe)到底會怎樣我倒是沒有研究過 我把您的code改成 var $ = function(id){return document.getElementById(id);}; $('ifa').src = 'javascript:alert("A");alert("B")'; $('ifb').src = 'javascript:alert("C");alert("D")'; 我剛剛試的結果 意外發現FF下會先出現A(很快來不急按) 然後被C蓋住 之後D 回到A 最後B 這有點兩個alert一起出現的味道(只是被蓋住了) IE的結果就是同一時間只有一個alert 然後ABCD 這跟browser的實作有關 我只能推斷 FF的alert出現時 容許其他的thread的alert也出現 (不確定是 出現兩個 一個被"蓋住" 或是同一個alert box然後內容被取代 在我的FF中沒辦法用滑鼠移動alert box) 而IE的UI不容許這種情況出現 然後回到問題 在兩個thread併行下 ACBD交叉出現我覺得是有可能的 (但我不知道哪個browser可以 也沒試著去製造出來過) 但是在一個event-driven 的single thread中(前篇文章) 是不會發生的 一個callback只會執行完在去執行下一個 不會互相跳來跳去 ============== 各家瀏覽器對alert的實作略有不同 一般當alert出現時 產生alert那段程式會暫停 直到按了之後在繼續 然而有些瀏覽器在alert出現時 會繼續dispatch的動作 dispatch進去的handler中 如果是UI trigger的 他不會執行 但如果是non-UI 的event handler 像是ajax的callback 在某些browser中是會同時執行的 即使你的alert還掛在那裏 所以用alert debug的習慣是非常不好的 在你還沒按下時 可能有東西就跑起來了 以致於你alert出來的變數也有可能被影響 而看到錯的值 真的用在application中更是有可能造成錯誤 (confirm,prompt等等都一樣) 根據你甚麼時候按下去 你的那段程式才會繼續跑 但是你的non-UI event在背後一樣的dispatch然後fire (如page load,timeout) 所以希望大家改掉直接用這種東西當UI的習慣 避免不必要的timing issue 全部的UI都要自己兜出來比較好 === 這裡就有現成的例子 剛剛用FF看 好像是CDAB (按掉CD時A或若隱若現) 如果你沒有注意那個若隱若現的A 你就會以為他的順序真的是CDAB這樣 然而如果你改成console.log("A") 就會知道他的真正的順序是ABCD 給大家參考:D ※ 引述《senser (彷彿曾經一起死過)》之銘言: : 跟大家分享一下 我對一般常見的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 (自立而後立人。)》之銘言: : : 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
文章代碼(AID): #1EjUUMsi (Ajax)
討論串 (同標題文章)
文章代碼(AID): #1EjUUMsi (Ajax)