我正在开发一个使用 jQuery 的网络应用程序,并且在测试时我得到了一些看起来可能是竞争条件的东西。尽管我尽了最大努力,但我不确定如何继续。
密码在GitHub ,但我将在此处总结奇怪的行为。
早期 AJAX 请求
我有一些代码需要 AJAX 调用并准备好 DOM。为了加快速度,我在 $(document).ready() 事件触发之前进行 AJAX 调用。在链接的 JS 文件中,这是“init”函数。此函数调用 _build_site_select,它设置 AJAX 请求。完成后,将调用 _on_site_list_success。
在 $(document).ready() 上
当我到达 ready() 时,我进行了需要同时触发 AJAX 和 ready() 事件的调用。在链接代码中,这是 populate_site_select 调用。由于调用 ready() 时 AJAX 可能未完成,因此我检查了在 AJAX 操作完成后设置的变量,并使用 setTimeout 延迟对 populate_site_select 的调用(如果完成时间还早)。变量 site_list_ready 在 AJAX 调用完成时设置,并在需要站点列表在执行前完全完成的函数中检查。
预期和观察到的行为
我希望看到的行为是 populate_site_select 仅在 _on_site_list_select 中的对象/关联数组完全填充后才会被调用。然而,这并非总是如此。有时,当我到达 populate_site_select 时,数组仅部分填充 - 它失败的方式似乎是一致的(它始终是数组中的相同单个条目,而不是我期望的 ~30 左右)。
我尝试过的
我还尝试向 _on_site_list_success 调用添加一个 setTimeout 调用,这进一步将数组的填充与 site_list_ready 变量的设置分开。但是,这并不能解决问题。
我知道从 AJAX 调用返回的 JSON 数据是正确的(我可以在 chrome 调试器中查看它),如果我稍后检查站点列表变量的值,(在页面加载完成后)它是正确的人口稠密。
这似乎不是一个不寻常的场景,我很难相信这个错误是在 Chrome 中(尽管我没有用其他浏览器测试过这个)。我做错了什么?
最佳答案
我没有尝试下面的代码,但 jQuery 的 Deferred
对象可以帮助您。
var domReady, ajax;
domReady = jQuery.Deferred();
jQuery(function () {
// on DOM ready
domReady.resolve();
});
ajax = jQuery.ajax({
url: '/path/to/file',
type: 'GET',
dataType: 'xml/html/script/json/jsonp'
});
jQuery.when(domready, ajax).then(doneCallbacks, failCallbacks);
基本上,您有两个延迟对象,一个处理 DOM 就绪状态,第二个处理 AJAX 调用;我们手动管理第一个对象,在 DOM 准备好时解析它;第二个由 jQuery 本身自动管理($.ajax
对象是 Deferred
对象,并在 AJAX 调用成功时解析)。
最后,使用 jQuery.when()
我们观察延迟对象的状态,当它们都被解析时,doneCallback
被解雇;如果两个对象之一被拒绝,则 failCallback
被触发。
因此,doneCallbacks
是将在解析两个 Deferred 对象后调用的函数,以便 DOM 准备就绪并且 AJAX 调用已进行并成功。
请参阅 jQuery.when()
的文档和 Deferred
objects
关于javascript - 尝试在 Chrome 中使用 jQuery 同步 AJAX + .ready() 时出现不可预测的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10364447/