【问题标题】:How are $.ajax callbacks handled on the stack? (Firefox vs Chrome vs ... )堆栈上如何处理 $.ajax 回调? (Firefox vs Chrome vs ...)
【发布时间】:2016-11-17 00:50:47
【问题描述】:

晚上好,伙计们-

我注意到不同的浏览器似乎以不同的方式处理回调。

例如,Firefox 似乎让 $.ajax.done({}) 回调中断当前的 javascript 指令,但 Chrome 在所有当前指令完成之前不会处理 $.ajax.done({}) 回调.这就像 Chrome 将调用发送到指令 queue 的末尾,而 Firefox 将其添加到指令 stack 的顶部。

(请记住,这可能是完全不正确的术语 - 我真的希望这是发布此内容的正确位置)

概括我的最佳猜测的显式示例:

function load_a_bunch_of_stuff()
    $.ajax({
        // ajax things here - e.g. load 10,000 whatevers from a server

    }).always(function() {
        ajaxStatus = "done!"
    });
}

function do_things_with_loaded_stuff() {
    // Loops as long as the status is "running" and the User is 
    // willing to retry:
    while (ajaxStatus === "running" && 
        confirm("Waiting on ajax, try again?"));

    // Do some cool stuff after the $.ajax call finishes
}

// --
// Main: (Assume do_things_with_loaded_stuff() is called before the 
//   load_a_bunch_of_stuff() finishes)

var ajaxStatus = "running";
load_a_bunch_of_stuff();
do_things_with_loaded_stuff();

-- 我的最佳猜测--

在本例中 - 循环将一直运行,直到 Firefox 允许 .always({}) 将“ajaxStatus”更改为“完成!” (可能在用户尝试单击确定时)然后我们可以继续。

但是在 Chrome 中,.always({}) 永远不会触发,因为(我猜)回调是在当前指令集完成之后执行的。换句话说,由于 .always({}) 被添加到指令集的末尾(而不是在下一个插槽中),因此它卡在循环中并且永远不会到达 .always({})。

此示例与我最近在尝试在两个浏览器之间进行开发时遇到的问题类似。有谁知道这个解释是否属实?

谁能真正解释发生了什么?

【问题讨论】:

  • 如果你没有confirm() 调用,回调将永远不会被允许运行。
  • 应该globalFlagajaxStatus
  • 我在小提琴中复制了这个:jsfiddle.net/barmar/wmjeh8mo
  • 我认为您看到的是 Firefox 在等待您响应 confirm() 对话框时运行异步代码,但 Chrome 没有。我不确定这是否被指定,所以你可能不应该依赖任何一种方式。
  • 我一直在尝试查找有关模式提示如何与事件循环交互的任何信息,但我的谷歌搜索都没有找到任何信息。

标签: javascript ajax google-chrome firefox


【解决方案1】:

这不是特定于 AJAX,它只是关于异步代码。

当您处于来自confirm()prompt()alert() 的模式对话框中时,Firefox 允许异步回调运行。 Chrome、Safari 和 Internet Explorer 不会。

这可以使用setTimeout() 来演示,它不需要$.ajax

function load_a_bunch_of_stuff() {
  setTimeout(function() {
    ajaxStatus = "done";
  }, 3000);
}

function do_things_with_loaded_stuff() {
  // Loops as long as the status is "running" and the User is 
  // willing to retry:
  while (ajaxStatus === "running" &&
    confirm("Waiting on ajax, try again?"));
  $("div").text("Done");

}

var ajaxStatus = "running";
load_a_bunch_of_stuff();
do_things_with_loaded_stuff();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  Running
</div>

请注意,如果您取消confim() 调用,您应该期望循环在所有浏览器上无限运行,因为任何 Javascript 引擎都不应该允许异步回调中断主流程。

【讨论】:

  • 完美!谢谢巴尔玛!
猜你喜欢
  • 2011-10-11
  • 2010-09-27
  • 2014-01-23
  • 2012-06-23
  • 1970-01-01
  • 1970-01-01
  • 2015-06-17
  • 2011-11-24
  • 1970-01-01
相关资源
最近更新 更多