为什么xmlhttprequest函数open()和send()位于函数的末尾

时间:2018-09-18 15:57:15

标签: javascript xml

我一直在自学php和xml(以及其他语言),并且在进行w3schools的xmlhttprequest教程时,我注意到open()和send()函数位于函数的末尾,而不是在函数的末尾或出来。这有点令人困惑,因为如果尚未发送请求,如何从服务器获得响应?我可能错过了一些简单的事情,如果是这样,我道歉,但是有人可以帮助我解决我的困境吗?预先感谢

function loadDoc() {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
     document.getElementById("demo").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "ajax_info.txt", true);
  xhttp.send();
}

2 个答案:

答案 0 :(得分:0)

读取数据的代码将在一个单独的函数中,该函数被分配为事件处理程序。

该功能直到收到响应后才会运行。

相关:How do I return the response from an asynchronous call?

答案 1 :(得分:0)

这在现代浏览器上可能无关紧要,但从根本上讲,您可以在发送呼叫之前进行设置。特别是,这样所有处理程序都在 之前被附加,要求XHR做某事。比较:

// Example 1
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", function() {
    // Got the data
});
xhr.open("GET", "http://example.com");
xhr.send();

使用

// Example 2
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://example.com");
xhr.send();
xhr.addEventListener("load", function() {
    // Got the data
});

浏览器不是单线程的,尽管它们在单个主线程(以及您创建的所有Web Worker)中运行JavaScript代码。因此,可能(尽管非常不可能),对于示例2,如果资源位于浏览器的缓存中,则单独的线程处理网络调用可能会触发load JavaScript线程上的sendaddEventListener调用之间发生事件,请参见未注册任何处理程序,并且不将任务排队等待事件循环调用该处理程序。而对于示例1,如果它在send时立即触发加载事件,它将看到一个附加的处理程序并将请求的任务排队(稍后在事件循环处理该任务时运行)。 >

以下是该假设情况的示例,显示了线程交互:

Example 1 - Highly Theoretical Scenario

JavaScript Thread                          Network Thread
-----------------------------------------  --------------
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", function() {
    // Got the data
});
xhr.open("GET", "http://example.com");
xhr.send();
    (Within send: Start the send, handing
    off to the network thread)
                                           1. Start a GET on `xhr`
                                           2. It's in cache, are there any load
                                              handlers registered on `xhr`?
                                           3. Yes, queue a task to call the handler
(Done with current task)
(Pick up next task)
Call the handler

vs

Example 2 - Highly Theoretical Scenario

JavaScript Thread                          Network Thread
-----------------------------------------  --------------
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://example.com");
xhr.send();
    (Within send: Start the send, handing
    off to the network thread)
                                           1. Start a GET on `xhr`
                                           2. It's in cache, are there any load
                                              handlers registered on `xhr`?
                                           3. No, don't queue a task to call 
                                              the handler
xhr.addEventListener("load", function() {
    // Got the data
});
(Done with current task)
(Pick up next task)
(No task, do nothing)

非常怀疑,任何当前的浏览器实际上都可以做到这一点(示例2),而且我不知道XHR过去曾遇到过这样的问题。但这在理论上是可能的,大约在2008年,存在一个非常相似的问题,在为src挂起之前,在img元素上设置load。但是,浏览器已解决了该问题,我很惊讶地发现它们现在可以接受上述示例2的情况,即使它们过去可能不在某个时候。

在实践中,我怀疑这很重要。但是如果我使用XMLHttpRequest(我不使用fetch),我仍然会使用Example 1。