【问题标题】:Handling jQuery promises that can fail for multiple reasons处理可能因多种原因而失败的 jQuery 承诺
【发布时间】:2013-05-18 06:27:09
【问题描述】:

我有一个函数upload_image,它从表单上传文件并返回代表ajax 请求的promise。但是,用户可能尚未在该表单上选择文件,在这种情况下,我无法返回承诺,因为不会有 ajax 请求。但是,调用upload_image 的代码需要返回一个ajax 请求的promise,所以done() 和fail() 函数假定ajax 请求完成或失败。所以问题是,如果用户已经选择文件的前提条件失败,upload_image 应该返回什么?

换句话说,处理可能因不同原因失败的失败承诺的最佳做法是什么?

我考虑返回一个已经失败的承诺,并带有一个字符串“请选择一个文件”,然后在失败函数中检查它,但这似乎很棘手。我还考虑将验证和 ajax 提交拆分为两个不同的函数,但对于这么小的功能来说,这似乎开销太大。

upload_image().done(function(){
  // image uploaded succesfully
}).fail(function(jqxhr){
  // error uploading OR image was not selected - what's the best way to handle this?
});

// pseudocode
function upload_image() {
  if (!user_has_selected_a_file) {
    // what to do here? maybe:
    // return new $.Deferred().reject('Please select a file');
  } else {
    return $.ajax();
  }
}

【问题讨论】:

  • 为什么返回一个失败的promise看起来很老套?这对我来说似乎很合理。
  • 这并不比仅仅返回一个失败的承诺更好,但是如果验证失败,你总是可以在 ajax 调用中立即调用abort(),就像在this fiddle中一样
  • @RayNicholus 看起来很老套,因为当没有任何延迟时,真的需要使用承诺。共识是,这是要走的路。

标签: javascript jquery ajax promise


【解决方案1】:

最简单的方法可能是模拟一个 jqXHR 错误,这样错误处理程序只需要表面上知道故障是真正的 jqXHR 错误还是合成的。

例如:

function upload_image() {
    if (!user_has_selected_a_file) {
        return $.Deferred().reject({simulated:true}, 'Please select a file', 'No file selected').promise();
    } else {
        return $.ajax(...);
    }
}

那么,以最简单的形式,upload_image() 的响应可以构造如下:

upload_image().done(function(data, textStatus, jqXHR) {
    // image uploaded succesfully
}).fail(function(jqXHR, textStatus, errorThrown) {
    //display textStatus and/or errorThrown as required
});

或者,如果您需要明确区分这两种类型的失败:

upload_image().done(function(data, textStatus, jqXHR) {
    // image uploaded succesfully
}).fail(function(jqXHR, textStatus, errorThrown) {
    if(jqXHR.simulated) {
        //display textStatus and/or errorThrown as required
    }
    else {
        //handle the genuine jqXHR and/or display textStatus and/or errorThrown as required.
    }
});

【讨论】:

  • 谢谢,看来像这样返回一个被 insta-rejected Deferred 是共识。
  • 是的,对于这种情况,返回一个准备被拒绝的承诺是一个完全有效的解决方法。
【解决方案2】:

在你的失败函数中处理它。您已返回延迟调用,使其成为对 .done / .fail 的逻辑调用

【讨论】:

    【解决方案3】:

    您可以手动创建一个Deferred object,立即使用.reject().rejectWith() 使其失败,然后从您的函数中返回它。您可以选择将指示错误的参数传递给它。

    附加到已经失败的 Deferred 对象的任何失败回调都将立即执行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-22
      • 1970-01-01
      • 1970-01-01
      • 2021-04-08
      • 2014-05-06
      • 1970-01-01
      • 2020-02-10
      • 2017-11-22
      相关资源
      最近更新 更多