假设我编写了一些执行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