当脚本执行时AJAX调用返回时,JavaScript中会发生什么?

假设我写了一些用myCallback执行AJAX调用的myCallback作为AJAX成功执行的callback方法。

假设当myCallback被asynchronous调用时,在我的页面上调用一些其他的JavaScript方法myFunction被调用。

一个操作优先于另一个吗? 他们都在同一时间吗? 怎么了?

假设当myCallback被asynchronous调用时,在我的页面上调用一些其他的JavaScript方法myFunction被调用。

一个操作优先于另一个吗? 他们都在同一时间吗? 怎么了?

浏览器上的JavaScript是单线程的(禁止使用web worker ,并且语法是明确的)。 所以myFunction将运行,直到它返回 – 有一些警告(继续阅读)。 如果ajax图层 myFunction运行时完成一个操作(很可能),并且需要调用callback,那么这个调用会被排队 。 下一次你的代码产生,队列中的下一个呼叫将被触发。

那么,我们似乎就不用担心竞争条件了。 大多数情况是这样,但有一些微妙之处。 例如,考虑这个代码:

 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图像时得到load事件,对吗?

错误。

JavaScript代码是单线程的,但其余的环境可能不是。 所以可能会发生这样的情况,在设置了img.src ,浏览器可能会看到它有一个可以使用的图像的caching副本,所以它会触发img.src = ...之间img上的load事件和img.onload = ...行。 由于我的处理程序还没有附加,我没有接到电话,因为当我附加我的处理程序,事件已经开除。

但是如果我们颠倒这些线,你可以看到排队的效果:

 var img = document.createElement('img'); img.onload = function() { // Handle the fact the image loaded foo(); }; img.src = /* ...the URL of the image... */; doSomethingElse(); doYetAnotherThing(); 

现在我正在设置src 之前挂钩事件。 如果事件在img.src = ...行和doSomethingElse行之间触发(因为浏览器在caching中有图像),则对我的处理程序的callback将被排队doSomethingElsedoYetAnotherThing在我的处理程序之前运行。 只有当控制通过我的代码时排队调用我的处理程序终于得到运行。 JavaScript代码是单线程的,但环境不是。

您也可以以非明显的方式屈服于主机环境。 例如,通过调用alert或其呼吸confirmprompt等等,这些函数就像现代JavaScript中的酸痛拇指一样突出,因为它们不是事件驱动的; 而是显示模式窗口时JavaScript执行被暂停。 但是正如鲍勃在这里深入的讨论中所指出的那样,这并不意味着在模式显示的时候,其他的代码都不会运行。 它仍然是单线程的,但是一个线程暂停在一个地方(通过模式),​​并用于在其他地方运行代码; 确实是非常好的区别。 (鲍勃也指出了一些事件处理 – 他的focus范例 – 似乎打破了这个规则,但事实并非如此,他的例子调用 focus ,然后调用事件处理程序,然后返回;与你自己调用函数)。Bob指出的项目的关键在于你的代码已经调用了东西,并且做了一些事情(显示模式对话框,引发blurfocus处理等)。

(特别是alert和气息,会造成各种各样的混乱,特别是focusblur ,我build议避免他们倾向于更现代的技术(它也可以看起来更好)。)

所以这些是答案一开始就提到的警告。 特别是,如果myFunction调用alert ,至less在Firefox上,ajax完成callbackalert期间运行(不会在大多数其他浏览器上)。 如果您想要了解在alerts等情况下是否发生了什么,请setTimeout testing页面testingsetTimeout和ajax; 你可以扩展testing去进一步。

这些答案都是错误的[编辑:至less有3-4错误,当这个答案被张贴]。 XHR事件放入事件队列/池中。 当单线程JavaScript线程不忙时,它将从事件池中获取下一个事件,并对其执行操作。 其中一个事件是你的XHR“AJAX”请求,它会触发callback,然后执行。 这就是所有没有中断的事件驱动系统的工作原理。

编辑 :Upvoting乔的回答链接到JavaScript是保证单线程? 并提到微妙的边缘情况。 非常翔实。

JavaScript类单线程看JavaScript是保证单线程? 。 所以答案是否定的,你的事件处理程序和你的函数可以同时运行,否则它们可能不运行。

AJAXcallback在下一个事件循环中运行。

阿贾克斯呼吁同时。 所以当ajax调用成功时,调用callback函数调用myfunction。

您可以通过提醒(“第一个”)来快速testing。 警报(“第二个”); 在这两个函数中,看看哪个模式popup窗口首先出现。 如果你的代码真的受到这个命令的影响,那么在这两个条件中join一些条件检查来防止/允许某些东西 原生js的速度与往返服务器的完整往返速度是截然不同的。 除非你有一些javascript在无限循环中运行,否则在其他函数执行期间返回的ajax调用的几率很小。

AJAX调用是“asynchronous”,意思是“发起一个呼叫,让我知道你要我什么时候回电话”。

总之:

 function DoSomething() { AJAXCall(Callback); } ... some time passes then ... function Callback() { Done(); } 

在这两个函数调用之间,任何事情都可能发生,当响应返回时,callback仍然会被调用,因为虽然javascript运行时是单线程的,但浏览器将堆栈调用以某种顺序发生(可能是它们的顺序而不是保证)。

这是一个耻辱,我只是拉我完成了我的旧网站,因为我有一个页面的典型例子,加载几个Ajax调用,因为每个调用回来,它会填充页面的各个部分。

尽pipe每个调用被“附加”到文档加载事件中,但是一次只能进行一次调用,但是服务器可以以任何顺序响应任何调用,因为服务器可能是multithreading的(可能是)。

可以认为javascript是一个虚拟框,浏览器可以通过一小块代码,它一次只能运行一次,但它可以按照它认为合适的顺序运行很多脚本(通常这是不可预测的,具有多个ajax调用,因为谁知道服务器何时可能会返回结果)

当ajax成功并调用myCallback ,它将同步运行。 所以myCallback就像其他的函数一样,你先调用它,或者先调用它,最后再运行。 他们不会在同一时间运行。