如果在ajax调用期间出现警报窗口会发生什么?

52

我在想,如果在执行ajax调用时,在浏览器窗口中弹出一个提示框,会发生什么。

举个例子,假设我有一个ajax调用:

$.ajax({
    url: ...,
    type: GET/POST,
    ...
    success: function(data){
        console.log(data);
    },
    error: ...
});

执行需要很长时间(10秒)的操作。在调用过程中,会弹出一个简单的JavaScript警告。

alert("hello!");

例如,如果发生以下情况会发生什么:

  1. ajax调用开始
  2. ajax调用获取数据
  3. 弹出警告
  4. ajax调用返回数据(弹出窗口仍然打开!)

由于JS是单线程的,我知道脚本执行将会停止,我只是想知道如果警告窗口没有“及时”关闭,ajax调用/响应会发生什么。

希望我表达得足够清楚,并且这不是一个“假”问题。谢谢


+1 很好的问题。我使用alert作为一种简易的断点,从未遇到过问题,但是...在点击OK之前,我不能记得曾经等待过比普通连接超时更长的时间来恢复脚本.. 我认为浏览器(视为javascript引擎和布局引擎的'包装器'/'驱动程序')将/应该继续运行并暂停javascript引擎,这样ajax数据将被排队等待进一步执行。但这不是一个适当的(参考和现实生活中的)答案.. - GitaarLAB
我也使用警报来提示用户消息,但我认为这不是一个很好的解决方案 :( - BeNdErR
1
附注:在原型设计期间,人们可以始终覆盖window.alert(在使用它们作为模拟消息/断点之后)以驱动自定义函数。 - GitaarLAB
没想到那个..不错。 - BeNdErR
警报与需要长时间运行的函数没有任何区别。想象一下以下情况会发生什么:1. ajax调用开始,2. 在ajax调用之后,调用一个非常耗时的函数,3. ajax调用在非常耗时的函数完成之前返回数据(现在怎么办?)4. 非常耗时的函数完成,5. 现在怎么办?现在你可以看到,无论是否看到警报,都没有任何区别。 - Stephen Chung
2个回答

60

尝试一下就会发现,弹出框会优先处理并阻止代码的继续执行。

在关闭弹出框后,假设 AJAX 请求在弹出框打开期间已完成,则将处理“success”函数(或error函数)。

需要注意的是,在显示弹出框时 AJAX 请求将继续运行(因此长时间运行的 AJAX 可以在弹出框打开时进行处理),只是您的脚本无法继续处理请求,直到关闭弹出框。

这里有一个工作示例,请注意,直到关闭弹出框后,数据才会被写入控制台。

还要注意的一点是,在关闭弹出框后,脚本将继续处理函数的其余部分(即在alert后面的代码),这有助于说明我的意思


这是一个很好的答案,还可以参考https://dev59.com/FXRB5IYBdhLWcg3wiHll。重要的是要理解,如果在AJAX请求开始后调用警报,则不会阻止该事件(请求)的完成,但其事件处理程序的处理将等待警报关闭。 - marekful
@AD7six:你在说什么? - musefan
@AD7six:为什么不行?这个 显示它在警报之前启动。 - musefan
如果您从最后一个示例中删除警报,则脚本仍将立即运行警报之前的代码,然后再运行“成功”回调。我认为代码将遵循启动代码时已建立的事件队列,而不关心警报。 - BeNdErR
@BeNdErR:当然,我并不是在暗示alert会导致代码先运行,只是想要明确一点,即你应该期望在处理响应之前函数已经完成,以防你可能依赖于响应被优先处理。 - musefan
显示剩余2条评论

11

HTTP请求将在后台继续运行和处理。

当JavaScript事件循环处于空闲状态时,readystatechange处理程序将被触发。

由于事件循环处于忙碌状态而该状态为真时,可能会跳过某些中间的准备就绪状态。


响应连接会保持开放并等待警报关闭吗? - BeNdErR
1
也许如果启用了管道技术。正如我在答案中所说:“HTTP请求将继续在后台运行和处理。”,如果响应/请求的正常行为是在接收到响应时关闭连接,则连接将被关闭。 - Quentin
@Quentin,这正是我怀疑的。我想知道...是否有一些规范/标准要求这种行为(这样可以安全地得出任何合理的浏览器都会这样做的结论)? - GitaarLAB
@Quentin 很抱歉打扰您,但我不明白一件事... 您说“HTTP请求将继续在后台运行并进行处理。”如果单线程被警报阻塞,它怎么能在后台运行呢?您是指服务器继续发送响应,等待客户端接受吗? - BeNdErR
2
XMLHttpRequest 是具有 JS 接口的本地控件。 它不依赖于 JS 事件循环(除了与 JS 通信之外,这就是为什么这样做是事件驱动的原因)。 - Quentin
3
重要的是要理解,虽然JavaScript是单线程的,但浏览器本身不是。 - Barmar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接