2013-05-02 133 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