假設我編寫了一些執行AJAX調用的JavaScript代碼,作爲AJAX成功執行時的回調方法,使用myCallback
。當腳本執行時AJAX調用返回時,JavaScript會發生什麼?
假設當我的頁面調用myCallback
異步調用時,我的頁面上調用了其他一些JavaScript方法myFunction
。
一個操作優先於另一個嗎?他們是否都在同一時間運行?怎麼了?
假設我編寫了一些執行AJAX調用的JavaScript代碼,作爲AJAX成功執行時的回調方法,使用myCallback
。當腳本執行時AJAX調用返回時,JavaScript會發生什麼?
假設當我的頁面調用myCallback
異步調用時,我的頁面上調用了其他一些JavaScript方法myFunction
。
一個操作優先於另一個嗎?他們是否都在同一時間運行?怎麼了?
假設,然後,其他一些JavaScript方法稱爲
myFunction
被調用我的頁面上時myCallback
是異步調用。一個操作優先於另一個嗎?他們是否都在同一時間運行?怎麼了?
瀏覽器上的JavaScript是單線程的(禁止使用web workers,而且語法明確)。所以myFunction
將運行,直到它返回 —與某些注意事項(繼續閱讀)。如果ajax層完成操作而myFunction
正在運行(它很可能)並且需要調用該回調,則該呼叫獲得排隊。下一次您的代碼產生時,隊列中的下一個呼叫將被觸發。
因此,看起來我們從不必擔心競賽狀況。大多數情況都是如此,但有些微妙之處。例如,考慮下面的代碼:
var img = document.createElement('img');
img.src = /* ...the URL of the image... */;
img.onload = function() {
// Handle the fact the image loaded
foo();
};
doSomethingElse();
doYetAnotherThing();
由於JavaScript的瀏覽器上是單線程的,我保證讓load
事件時加載圖像,對不對?
錯誤。
JavaScript代碼是單線程的,但其餘的環境可能不是。因此,它可以發生,將其具有的img.src
,瀏覽器可能會看到它有它可以使用圖像的緩存副本,所以它觸發的img
之間的img.src = ...
線和img.onload = ...
線load
事件。由於我的處理程序尚未附加,因此我無法接聽電話,因爲當我附加了處理程序時,該事件已經被解僱。
但是你可以看到排隊的效果,如果我們扭轉這些行:設置src
前
var img = document.createElement('img');
img.onload = function() {
// Handle the fact the image loaded
foo();
};
img.src = /* ...the URL of the image... */;
doSomethingElse();
doYetAnotherThing();
現在我掛鉤事件。如果img.src = ...
線和doSomethingElse
線(因爲瀏覽器在高速緩存中的圖像)之間的事件觸發,回調到我的處理程序獲取排隊。 doSomethingElse
和doYetAnotherThing
在我的處理程序執行之前運行。只有當控制通過我的代碼時,排隊調用我的處理程序才能最終運行。 JavaScript代碼是單線程的,但環境不是。
您也可以以非明顯的方式屈服於主機環境。例如,通過調用alert
或其breathren confirm
,prompt
等,這些功能的堅持像瘡大拇指,他們是現代的JavaScript,因爲他們不是事件驅動;相反,在顯示模式窗口時JavaScript執行被暫停。但是bobince在his in-depth discussion here中指出,這並不意味着當模式顯示時,其他代碼都不會運行。它仍然是單線程的,但是一個線程被暫停在一個地方(通過模式),並用於在其他地方運行代碼;確實是非常好的區分。 (鮑勃也指出了一些事件處理 —他focus
例如 —這似乎打破了這一規則,但它沒有他的榜樣調用focus
,進而調用事件處理程序,然後返回。沒什麼兩樣)Bob指出的項目的關鍵在於,您的代碼在主機環境中調用了一些東西,它會消失並執行某些操作(顯示模式對話框,觸發blur
和focus
處理程序,等等。)。
(alert
及其在特定的原因breathren種種污穢的,特別是圍繞focus
和blur
,我建議避免他們贊成更現代的技術(也可看約18倍更好)。)
所以這些是答案一開始提到的警告。尤其如果myFunction
電話alert
,至少在Firefox中的AJAX完成回調將得到alert
期間(不是大多數其他瀏覽器它會)上運行。如果你很好奇嘗試什麼呢,並在alerts
和這樣的,here's a test page測試setTimeout
和Ajax不會發生;你可以擴大測試的範圍。
ajax調用與同時。所以當ajax調用成功時,調用回調函數,然後調用myfunction。
雖然大多數情況是正確的,但不幸的是,這個誤解了這個問題:'myFunction'完全獨立於回調,並且不被調用回電話。 – ninjagecko
您可以快速測試此警報('第一個');警報('第二個');在這兩個函數中,看看哪個模式彈出窗口首先出現。如果你的代碼真的受到這個命令的影響,那麼在兩者中加入一些條件檢查來防止/允許一些東西。原生js的速度與往返於服務器的完整往返速度是截然不同的。除非你有一些javascript在無限循環中運行,否則在其他函數執行期間返回的ajax調用的機率很小。
Javascript類單線程見Is JavaScript guaranteed to be single-threaded?。所以答案是NO,你的事件處理程序和你的函數可以同時運行,或者它們可能不運行。
雖然這是一些實現技術上是可行的,程序員應該總是假設一個事件觸發模型嚴格遵守。除此之外的任何事情都會導致瘋狂。 – tjameson
這些答案都是錯誤的[編輯:這個答案被張貼時,至少有3-4錯]。 XHR事件放入事件隊列/池中。當單線程JavaScript線程不忙時,它將從事件池中獲取下一個事件,並對其執行操作。其中一個事件是你的XHR「AJAX」請求,它將觸發回調,然後執行。這就是所有沒有中斷的事件驅動系統的工作原理。
編輯:Upvoting喬的答案,鏈接到Is JavaScript guaranteed to be single-threaded?,並提到了微妙的邊緣的情況下。非常豐富。
AJAX調用是「asyncronous」,這意味着「火了一個電話,讓我知道你想讓我回電話時,即時通訊做了什麼」。
總之這樣:
function DoSomething() { AJAXCall(Callback); }
... some time passes then ...
function Callback() { Done(); }
這些2函數調用之間什麼都可能發生,回調仍然會被調用時響應返回因爲雖然JavaScript運行是單線程的瀏覽器將棧調用發生按照某種順序(可能是他們的訂單,但沒有保證)。
這是一個恥辱,我只是做拉住我的舊網站,因爲我有做負載幾個ajax調用頁面的經典例子,因爲每個電話回來,將填充頁面的各個部分。
儘管每次調用都「附加」到文檔加載事件,但一次只能進行1次調用,但服務器可以以任何順序響應任何調用,因爲服務器可能是多線程的(可能是)。
認爲JavaScript是一個虛擬框,瀏覽器可以在其中傳遞一小塊代碼,它一次只能運行一次,但它可以按照它認爲合適的順序運行很多腳本(通常這個多個Ajax調用是不可預知的,因爲誰知道服務器何時可能會返回結果)
我有一種感覺,瀏覽器在內部對這種行爲使用一個eventloop(如node.js)。如果是這種情況,你可能想談談如何eventloops工作。 – Raynos