2013-05-02 132 views
1

我正在給我的JavaScript的第一步,並試圖瞭解它是如何工作的。 我遇到了代碼執行順序的問題。Javascript執行代碼順序

var Parsed = [[]] 
var txtFile = new XMLHttpRequest(); 
alert("Trying to open file!"); 

txtFile.open("GET", "http://foo/f2/statistics/nServsDistrito.txt", false); 
txtFile.onreadystatechange = function() { 
if (txtFile.readyState === 4) { // Makes sure the document is ready to parse. 
    if (txtFile.status === 200) { // Makes sure it's found the file. 
     alert("File Open"); 
     allText = txtFile.responseText; 
     Parsed = CSVToArray(allText, ",") 
     } 
    } 
} 
txtFile.send(null); 

alert("Job Done"); 

問題是「作業完成」首先出現比「文件打開」。

但是該文件具有「作業完成」警報之後的代碼所需的信息。 我改變了「獲取」請求的異步部分,但沒有奏效。

當文件打開並且檢索到信息時,我能做些什麼來支持所有代碼? 當文件被打開和解析時,我可以使用readyState來停止代碼嗎?

感謝您的幫助。

更新:它現在可以工作,感謝所有。

+1

XMLHttpRequest是**異步**,open將與您的函數並行執行(並且當您的函數完成其作業以保持您的代碼「單線程」時,將執行onreadystatechanged)。 – 2013-05-02 09:09:51

+1

將最後3個'}'移到最下面。 – C5H8NNaO4 2013-05-02 09:12:04

+0

如果請求是同步的,那麼事件處理程序的用途是什麼?在'.send'和'alert(done)'之間移動事件處理程序中的代碼' – 2013-05-02 09:14:23

回答

0

這是因爲您正在使用異步函數。在使用異步功能時,您必須使用回調
回調是一個函數(例如,function cback()),您將其作爲參數傳遞給另一個函數(例如function async())。那麼,cback將在必要時被async使用。
例如,如果你正在做的IO操作,例如讀取文件或執行SQL查詢,回調可以用來處理一次檢索的數據:

asyncOperation("SELECT * FROM stackoverflow.unicorns", function(unicorns) { 
    for(var i=0; i<unicorns.length; i++) { 
     alert("Unicorn! "+unicorns[i].name); 
    } 
}); 

我們給asyncOperation作爲第二個參數是匿名函數「回調」,一旦查詢數據準備好就會執行。不過,雖然該操作正在處理您的腳本不堵塞,這意味着如果我們在前面的代碼之後加入這一行:

alert("We are not blocked muahahaha"); 

即完成之前的查詢和獨角獸出現將會顯示警告。

所以,如果你想後做一些異步任務完成,添加該代碼回調中:

asyncOperation("SELECT * FROM stackoverflow.unicorns", function(unicorns) { 
    for(var i=0; i<unicorns.length; i++) { 
     alert("Unicorn! "+unicorns[i].name); 
    } 
    //add here your code, so that it's not executed until the query is ready 
}); 

注:如@radhakrishna在註釋中open()功能也能正常工作指出以同步的方式,如果您通過true而不是false。這樣代碼將按照您的預期工作:換行,換句話說:同步。


回調可以用於很多東西,例如:

function handleData(unicorns) { 
    //handle data... check if unicorns are purple 
} 
function queryError(error) { 
    alert("Error: "+error); 
} 
asyncOperation("SELECT * FROM stackoverflow.unicorns", handleData, queryError); 

這裏我們使用兩個回調,一個用於處理數據和另一個如果發生(當然錯誤這取決於asyncOperation如何工作,每個異步任務都有自己的回調)。

+0

感謝您的迴應和解釋! :) – M1nga 2013-05-02 10:44:53

+0

不客氣。一旦你瞭解同步/異步工作如何看看這個:https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Synchronous_and_Asynchronous_Requests有一些有用的例子 – TheBronx 2013-05-02 10:46:40

0

XMLHttpRequest是一個異步操作。無論您的文件是否可用,或者即使沒有涉及網絡,也無關緊要。因爲它是異步操作,所以在任何順序/同步代碼之後,它將始終在之後執行。這就是爲什麼你必須聲明一個回調函數(onreadystatechange),當open返回文件內容時將被調用。

通過上面的解釋,您在此示例中的代碼將不正確。 alert行將立即執行,而不是等待文件內容準備就緒。這項工作只有在onreadystatechange執行完畢後才能完成,因此您必須將alert置於onreadystatechange的末尾。

觸發異步操作的另一種非常常見的方式是使用setTimeout,這會強制其回調函數異步執行。看看它是如何工作的here

編輯:通過將第三個參數設置爲openfalsehttps://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#open()),確實可以強制請求同步。儘管如此,您希望像這樣的請求同步的情況很少。考慮你是否需要它是同步的,因爲你將阻止你的整個應用程序或網站,直到文件被讀取。

+1

XMLHttpRequest不一定是異步的。 '.open'中的第三個參數可以設置爲false以使其同步。 – 2013-05-02 09:45:49