在JavaScript中会发生什么,当一个AJAX调用返回,而在脚本执行? [英] What happens in JavaScript when an AJAX call returns while the script is executing?

查看:168
本文介绍了在JavaScript中会发生什么,当一个AJAX调用返回,而在脚本执行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我写一些JavaScript执行AJAX调用与 myCallBack函数作为回调方法来执行时,AJAX成功。

假设再调用其他JavaScript方法 myFunction的正在我的页面调用时 myCallBack函数是异步调用。

难道一个操作取precedence比其他?难道他们都在同一时间运行?发生了什么?

解决方案
  

假设再调用其他JavaScript方法 myFunction的正在我的页面调用时 myCallBack函数是异步调用。

     

难道一个操作取precedence比其他?难道他们都在同一时间运行?发生了什么?

的JavaScript在浏览器上是单线程的(除非您使用网络工作者和语法是明确的) 。因此, myFunction的运行,直到它返回 —有一定的注意事项(请继续阅读)。如果阿贾克斯层完成操作的,而 myFunction的运行(这很可能也是),需要调用回调,这一呼吁得到的排队的。下一次你的code收益率,在队列中的下一个电话将被触发。

这似乎,那么,我们从来不用担心竞态条件。这主要是真实的,但也有细微之处。例如,考虑这个code:

  VAR IMG = document.createElement方法('IMG');
img.src = / * ...的图像的URL ... * /;
img.onload =功能(){
    //处理事实的图像加载
    富();
};
doSomethingElse();
doYetAnotherThing();
 

由于JavaScript的浏览器上是单线程的,我保证让负荷事件时加载图像,对吧?

错误。

的JavaScript 的code是单线程的,而环境的其余部分可能不是。因此,它可以发生的,已经设置了 img.src ,浏览器可能会看到它有它可以使用图像的缓存副本,所以它触发<$与C $ C>负荷事件的 IMG 的的 img.src = .. 线和 img.onload = ... 行。因为我的处理程序没有安装呢,我不来电,因为当我附上我的处理程序,该事件已经解雇了。

但是你可以看到排队的效果,如果我们扭转这些行:

  VAR IMG = document.createElement方法('IMG');
img.onload =功能(){
    //处理事实的图像加载
    富();
};
img.src = / * ...的图像的URL ... * /;
doSomethingElse();
doYetAnotherThing();
 

现在我挂钩事件的的设置的src 。如果 img.src = ... 线和 doSomethingElse 线之间的事件触发(因为浏览器有图像缓存),回调到我的处理程序获取的排队的。 doSomethingElse doYetAnotherThing 运行之前,我的处理程序。只有当控制了我的code确实给我的处理程序的排队调用最终得到运行。 JavaScript的code是单线程的,但环境不是。

您也可以产生宿主环境中无明显的方式。例如,通过调用警告或其breathren 确认提示等,这些功能伸出像疮大拇指,他们是现代的JavaScript,因为它们的不是的事件驱动;相反,JavaScript执行的同时会暂停模态窗口显示。但是,随着 bobince 指出了的他深入讨论这里,这并不意味着所有其它的code运行时的模态展示。它仍然是单线程的,但一个线程被挂起在一个地方(通过模式),​​并用于在此期间,其他地方运行code;一个非常精细的区分确实如此。 (鲍勃也指出了一些事件的处理和NBSP;&mdash;他的焦点例如&NBSP;&mdash;这似乎打破这个规则,但它没有他的榜样的电话<。 / em>的焦点,这反过来又调用了事件处理程序,然后返回,无异于在调用自己的函数),最关键的一点是鲍勃指出的项目有。在常见的是,你的code呼吁到的东西在做消失,并做了一些主机环境(显示一个模式对话框,火灾模糊焦点处理程序,等等)。

警告特别是其原因breathren各种污秽,特别是围绕焦点模糊,我建议避开它们,转而采用更加现代的技术(也可看约18倍为佳)。)

因此​​,这些都是在回答一开始提到的注意事项。特别是,如果 myFunction的要求警告,至少在Firefox浏览器的AJAX完成回调的在得到运行警告(它不会对大多数其他浏览器)。如果你很好奇尝试什么呢,并没有发生在警报键,这样,这里测试页测试的setTimeout 和Ajax;你可以扩展测试走得更远。

Suppose I write some JavaScript that performs an AJAX call with myCallback as a callback method to execute when the AJAX succeeds.

Suppose then that some other JavaScript method called myFunction is being invoked on my page when myCallback is invoked asynchronously.

Does one operation take precedence over the other? Do they both run at the same time? What happens?

解决方案

Suppose then that some other JavaScript method called myFunction is being invoked on my page when myCallback is invoked asynchronously.

Does one operation take precedence over the other? Do they both run at the same time? What happens?

JavaScript on browsers is single-threaded (barring your using web workers, and the syntax for that is explicit). So myFunction will run until it returns — with certain caveats (keep reading). If the ajax layer completes an operation while myFunction is running (which it very well may) and needs to invoke the callback, that call gets queued. The next time your code yields, the next call in the queue will be triggered.

It might seem, then, that we never have to worry about race conditions. That's mostly true, but there are subtleties. For instance, consider this code:

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

Since JavaScript on browsers is single-threaded, I'm guaranteed to get the load event when the image loads, right?

Wrong.

The JavaScript code is single-threaded, but the rest of the environment probably isn't. So it can happen that, having set the img.src, the browser may see that it has a cached copy of the image it can use, and so it triggers the load event on the img between the img.src = ... line and the img.onload = ... line. Since my handler isn't attached yet, I don't get the call, because by the time I've attached my handler, the event has already fired.

But you can see the effect of queuing if we reverse those lines:

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

Now I'm hooking the event before setting src. If the event fires between the img.src = ... line and the doSomethingElse line (because the browser has the image in cache), the callback to my handler gets queued. doSomethingElse and doYetAnotherThing run before my handler does. Only when control passes out of my code does the queued call to my handler finally get run. The JavaScript code is single-threaded, but the environment is not.

You can also yield to the host environment in non-obvious ways. For instance, by calling alert or its breathren confirm, prompt, etc. These functions stick out like the sore thumbs they are in modern JavaScript because they aren't event driven; instead, JavaScript execution is suspended while a modal window is shown. But as bobince points out in his in-depth discussion here, that doesn't mean none of your other code will run while that modal is showing. It's still single-threaded, but the one thread is being suspended in one place (by the modal) and used to run code elsewhere in the meantime; a very fine distinction indeed. (Bob also points to some event handling — his focus example — that seems to break this rule, but it doesn't. His example calls focus, which in turn calls the event handlers, and then returns; no different from you calling your own functions.) The key thing the items that Bob points out have in common is that your code has called into something in the host environment that does goes away and does something (shows a modal dialog, fires blur and focus handlers, etc.).

(alert and its breathren in particular cause all sorts of nastiness, particularly around focus and blur, and I recommend avoiding them in favor of more modern techniques (which can also look about 18x better).)

So those are the caveats mentioned at the outset of the answer. And in particular, if myFunction calls alert, at least on Firefox the ajax completion callback will get run during the alert (it won't on most other browsers). If you're curious to try out what does and doesn't happen during alerts and such, here's a test page testing setTimeout and ajax; you could extend the tests to go further.

这篇关于在JavaScript中会发生什么,当一个AJAX调用返回,而在脚本执行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆