【问题标题】:Jquery AJAX promise with always break when ajax failJquery AJAX 承诺在 ajax 失败时总是中断
【发布时间】:2017-09-29 03:40:19
【问题描述】:

我有一个包含多个 ajax 请求的循环。 每个 ajax 都是通过总是回调来管理的。 每个 ajax 都被推送到 promises 数组中。 最后 $.when 总是被使用。

如果所有$.ajax 都成功了$.when.apply($, promises).always(...); 当所有$.ajax 调用成功时调用。

但例如在 3 $.ajax 调用第二个失败时,$.when.apply($, promises).always(...); 仅在第二个之后触发,而不是在所有 3 $.ajax 调用成功时触发。

有什么帮助吗? 跟着代码

$(".upload_all").bind("click", function() {
  var confirmed_count = 0;
  var error_count = 0;
  var promises = [];

  to_uploads.each(function(index,val) {
    var elem = $(this);
    var promise = $.ajax({
      url: "/upload/storeUploadedFile",
      type: 'POST',
    }).always(function(data_or_jqXHR, textStatus, jqXHR_or_errorThrown) {
      if (textStatus === "success") {
        // ..
      } else {
        // ..
      }                  
    });

    promises.push(promise);
  });

  $.when.apply($, promises)
    .always(function() {
      console.log("Promises Always! ") // do other stuff
    });
}

【问题讨论】:

  • .always 甚至与 jquery 承诺相关吗?是的,我猜我只是从来没有在那种情况下使用过它。 jquery 1.6+
  • 好的,所以,你的 $.when() 创建了一个可以解决或拒绝的承诺。如果其中一个承诺被拒绝,整个事情会立即拒绝,跳过任何尚未完成的事情。这表明你有一个承诺,如果它没有达到他们所有人的目的,那么它就会失败。如果您想等待它们全部运行而不考虑失败,则必须拦截失败并将其转换为成功。

标签: javascript jquery ajax promise


【解决方案1】:

正如@kevin-b 所提到的,如果传递给它的任何承诺被拒绝,$.when 返回的承诺(与Promise.all 几乎相同)将被拒绝。您可能希望这样做,以通知用户某些上传不成功。

$.ajax(..).always(与promise.finally 相同)的意思是“当这个promise 被拒绝或解决时执行这个回调”。您可能希望在所有 ajax 调用成功时执行某些操作,或者在其中任何一个调用失败时执行其他操作。为此使用Promise.all(promises).then(...).catch(...)

$(".upload_all").bind("click", function() {
  var confirmed_count = 0;
  var error_count = 0;

  var promises = to_uploads.map(function(index,val) { // using map instead of each here saves us a couple of steps
    var elem = $(this);

    return $.ajax({
      url: "/upload/storeUploadedFile",
      type: 'POST',
    })
      .then(function() { confirmed_count += 1; })
      .catch(function() {
        error_count += 1;
        return Promise.reject(); // Return a rejected promise to avoid resolving the parent promise
      });
  });

  // You can use the native API here which does not require doing the `apply` hack
  Promise.all(promises)
    .then(function() { alert('All uploads successful'); })
    .catch(function() { alert(`Successful uploads: ${confirmed_count}. Failed uploads: ${error_count}`); }
}

请记住,JQuery 使用了 Promise 的替代实现,但它们仍然响应原生 API:

  • .then(JQuery 风格的.done):附加一个回调以在成功时运行
  • .catch(JQuery 风格中的.fail):附加一个回调以在错误时运行。除非返回被拒绝的承诺,否则这将解决承诺。
  • .finally(JQuery 风格的.always):附加一个回调以在任何其他回调运行后运行,尽管承诺被拒绝或解决。

【讨论】:

  • 我在哪里评论 // 做其他事情 我希望只用一个摘要提示用户上传成功和上传失败。你说“意味着'当这个承诺被拒绝或解决时执行这个回调'”但它并没有像我试图解释的那样发生,因为当一个 ajax 失败时回调被触发。
  • 您可以迭代我的更改并将对失败的 API 调用的引用推送到一个数组中。您不能使用always,因为它会在所有 AJAX 调用成功或任何失败时触发。查找修改。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-28
  • 1970-01-01
  • 2014-06-14
  • 1970-01-01
  • 2013-10-15
相关资源
最近更新 更多