带有 async:false 的 Chrome 和 Safari ajax 问题

tin*_*der 2 ajax jquery google-chrome

我在网上到处都看到了这个,但我无法修复我的代码来避免这个问题,只是我有一个 ajax 函数,当点击某些按钮时会触发它,有时我想要一个指示器(加载动画)显示,有时不是,所以我构建了我的函数:

function doAjax(action, todo, items, error_num, hide_indicator) {
  items.action = action;
  items.do = todo;
  var postedObj;

  $.ajax({
    type: 'post',
    dataType: 'html',
    url: ajaxURL,
    data: items,
    async: false,
    beforeSend: function() {
      if (!hide_indicator) showIndicator();
    },
    success: function(data) {
      if (data) {
        ajaxObj = JSON.parse(data);
        if (ajaxObj.ok) {
          postedObj = ajaxObj;
        } else {
          alert(ajaxObj.error);
          postedObj = false;
        }
      } else {
        alert('[' + error_num + '] Something went wrong.');
        postedObj = false;
      }
      if (!hide_indicator) hideIndicator();
    },
    error: function() {
      alert('[' + error_num + '] Something went wrong.');
      postedObj = false;
      if (!hide_indicator) hideIndicator();
    }

  });
    return postedObj;
}
Run Code Online (Sandbox Code Playgroud)

这是我在按钮上执行的调用函数的操作:

$(document).on('click', '.ad-single', function() {
  var addataObj = doAjax('post_requests', 'get-ad-info', {"id": $(this).data('ad')}, '158', false); // false means DON'T hide the indicator
  if (addataObj) {
    loadContent(addataObj.ad);
  }  
});
Run Code Online (Sandbox Code Playgroud)

好的,现在,Firefox 上的一切都按预期工作,当我单击我的按钮时,指示器显示并等待 ajax 返回数据,然后再次隐藏指示器。

这在 Chrome 和 Safari 上不起作用,该函数工作正常并按预期返回数据,但似乎hideIndicator()立即调用了该函数,我不知道如何解决这个问题。

火狐:

在此处输入图片说明

Chrome 和 Safari:

在此处输入图片说明

31p*_*piy 5

使用async: false是邪恶的。互联网上充斥着此类帖子,包括 Chrome 和 Safari 在内的许多浏览器都会在发出同步 AJAX 请求时向您发出大量警告。

幸运的是,jQuery 的承诺可以用来解决您的问题。它不会改变您的函数的工作方式,并且也利用 promise 的力量来发出异步请求。

您可以按如下方式修改现有函数,使其返回 AJAX 承诺,而不是结果。

function doAjax(action, todo, items, error_num, hide_indicator) {
  items.action = action;
  items.do = todo;

  return $.ajax({
      type: 'post',
      dataType: 'html',
      url: ajaxURL,
      data: items,
      beforeSend: function() {
        if (!hide_indicator) showIndicator();
      }
    })
    .then(function(data) {
      if (!hide_indicator) {
        hideIndicator();
      }

      if (data) {
        ajaxObj = JSON.parse(data);

        if (ajaxObj.ok) {
          return ajaxObj;
        }

        alert(ajaxObj.error);
        return false;
      }

      alert('[' + error_num + '] Something went wrong.');
      return false;
    }, function() {
      if (!hide_indicator) {
        hideIndicator();
      }

      alert('[' + error_num + '] Something went wrong.');
      return false;
    });
}
Run Code Online (Sandbox Code Playgroud)

在这里,.then可以使用一个函数来预处理响应,并将适当的值返回给后续的 Promise 处理程序。

后续的 promise 处理程序可以按如下方式实现,它调用doAjax函数,并通过预处理对返回的值做出反应。

$(document).on('click', '.ad-single', function() {
  doAjax('post_requests', 'get-ad-info', {"id": $(this).data('ad')}, '158', false)
    .then(function(addataObj) {
      if (addataObj) {
        loadContent(addataObj.ad);
      }
    });
});
Run Code Online (Sandbox Code Playgroud)

在这里,.then()链接与前一个.then(), 并对返回的值(在 中接收addataObj)做出反应。请注意,它仅对 AJAX 调用成功作出反应。如果您还想处理错误响应,则需要将第二个参数作为函数传递给.then()处理程序。

希望这能解决您的问题。