【问题标题】:Receiving warning about Synchronous XMLHttpRequest in asynchronous function在异步函数中收到有关同步 XMLHttpRequest 的警告
【发布时间】:2015-09-07 19:22:09
【问题描述】:

我的浏览器(或者更具体地说是 JQuery 框架)向浏览器的控制台打印以下警告:

主线程上的同步 XMLHttpRequest 已被弃用,因为它会对最终用户的体验产生不利影响。如需更多帮助,请查看http://xhr.spec.whatwg.org/

我理解警告,但不明白它出现的原因。据我了解, asyncFunct() 的调用 异步的,因此不应打印警告消息。

我正在使用这个 JavaScript 代码:

var i18nObject;

$(document).ready(function () {
    // execute asyncFunct() asynchronously
    setTimeout(asyncFunct, 3000);
});

function asyncFunct() {
    alert(i18n("rejoin.title"));
}

function i18n(key) {
    if (typeof i18nObject == 'undefined') {
        // i18n not loaded yet, need to load it first
        $.ajax({
            url: 'UrlTo/i18n.json',
            async: false,
            dataType: 'json',
            success: function (response) {
                i18nObject = response;
            }
        });
    }
    if (i18nObject.hasOwnProperty(key)) {
        // key found
        return i18nObject[key];
    } else {
        // key not found
        return key;
    }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>

面对一些关于async: false 的担忧(来自 cmets):这是故意选择的,因为我需要函数返回一个值。我知道如果他们锁定 UI,使用同步调用是个坏主意。但是为什么这适用于我的问题呢?我希望对 asyncFunct() 的调用是异步的。

为什么我会收到此警告,是否可以禁用它? (以防止控制台中出现不必要的文本)

【问题讨论】:

  • 它明确告诉你不要使用async: false,,这首先是一种糟糕的做法。在成功回调中处理您的响应。见how-to-return-the-response-from-an-asynchronous-call
  • 该警告表明如果你想使用async: false,你应该在主线程之外进行。看看使用Web workers
  • 我现在通过将 i18n() 调用移动到另一个 AJAX 调用的完成函数中来解决这个问题。这对我的特定问题很有用(因为无论如何我都需要拨打电话),但我仍然对为什么首先显示此消息感兴趣。
  • @charlietfl 感谢您的链接。在我的情况下,如果 i18nObject 之前没有加载,i18n() 函数应该只执行 AJAX 调用。有没有办法在不进行不必要的 AJAX 调用的情况下返回它(或返回“稍后再给我打电话,我仍在获取价值”)?
  • 谷歌错误的完整解释

标签: javascript jquery ajax asynchronous


【解决方案1】:

编辑

实际上,由于您将同步调用置于超时内,因此调用确实似乎是异步发生的,正如您正确指出的那样(参见this jsbin 示例): p>

setTimeout(function() {
  $.ajax({
    method: 'GET',
    url: 'http://api.openweathermap.org/data/2.5/weather?q=London,uk',
    success: function(res) {
      console.log(res);
    },
    async: false
  });
}, 1000);

console.log('something synchronous');

如果您打开控制台,您会注意到(如预期的那样)something synchronous 首先被记录,然后一秒钟多一点后,我们的 API 的结果被记录。

所以我觉得这个问题有两个部分需要解决。

第一部分是,当您可以完全避免超时并简单地使您的 XMLHttpRequest 自然异步时,为什么要使用已弃用的 API 强制同步调用异步发生?

第二部分是关于抑制警告。似乎警告错误地发生了,但警告并没有考虑您在超时内发出同步请求的事实。它只是查看您正在使用已弃用的 API 的事实。换句话说,警告只关心被弃用的 API 本身的使用,而不关心具体的实现。

但是,如果您真的想抑制这些警告,那就只能是孤注一掷了(参见this answer 的示例):

// define this as an empty function in your own code
console.log = function() {};

原答案

据我了解,asyncFunct() 的调用是异步的,因此不应打印警告消息。

错误。

您的调用不是异步的。它是同步的,因为你有async: false

此警告是因为同步请求阻塞了主线程(例如,处理 UI 的同一线程)。这可能会破坏用户使用网站/应用程序的体验。因此,警告会显示在控制台中。

【讨论】:

  • 谢谢,这解释了警告,但你能解释为什么调用是同步的吗?我读过stackoverflow.com/a/7374037/3298787,它(据我了解)说“使用 setTimeout() 调用函数使其异步”
  • 谢谢,这是一个很好的答案。我使用同步调用的原因是:我需要从 json 对象(服务器端,基于客户端 accept-language,生成)加载翻译后的消息。我想避免对对象进行不必要的调用(-> 将其缓存在“i18nObject”中)。为了简化这个过程,我为它指定了一个函数:“i18n()” 当我已经从主线程(--> asyncFunct())取消同步并且我想避免时,我只需要这个函数带有回调函数的过度复杂化 i18n()
  • @Nijin22,没有问题。好的,这是有道理的。我不确定是否有比你正在做的更好的方法,但我可能会花一些时间调查你是否能找到一种不那么“hacky”的方式正在做。但是您所说的概念是有道理的(即在客户端缓存数据库对象)。
  • 谢谢。我尝试了很多替代方案(生成和本地化的 javascript、在 HTML 中预加载的消息等),但没有找到比我当前框架更好的替代方案。我也不喜欢当前的解决方案,但至少它确实有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-27
  • 2012-07-25
  • 1970-01-01
相关资源
最近更新 更多