拒绝Javascript承诺和错误处理

时间:2016-05-21 15:41:54

标签: javascript ajax error-handling promise es6-promise

我正试图围绕正确的方式指出.then()内的失败。

如果promise没有失败,(即返回promise的操作会'正常工作,例如返回状态200的AJAX请求',但我认为结果无效,通常我'做一个弹出窗口,向用户解释问题,并做一个“返回false;”尽早退出方法。

然而,对于承诺,如果来自.then(),我想做类似的事情,我一直认为我应该做的是抛出一个错误,并且可能让这个被它抓住.catch(),我已经链接。

我担心的是,我想区分成功的承诺中的操作,但我不喜欢结果的承诺,以及承诺中的失败操作。

例如,如果我执行一个AJAX调用并且它失败了404,那就不可以恢复,所以用弹出窗口拒绝说出“出错了”这个似乎是合适的。

但是,如果AJAX请求成功(返回状态200),但响应表明某些内容不正确(就像用户没有填写具有正确值的字段),那么我想以某种方式处理,这可能不仅涉及带有消息的弹出窗口(例如,可能涉及DOM操作,红色文本等,如果它是404,我可能不想做的事情。)

以下两个例子可以更好地解释我的意思。

第一个是带回调的原始实现,第二个带有promises(用Q promise库包装ajax调用以使其成为正确的承诺)。

回拨版本:

    $.ajax({
    url: "/cars/1",
    type: "GET",
    contentType: "application/json; charset=utf-8",
    dataType: "json"
})
.done(function (data) {
    if (!data.IsSuccessful) {
        //The request was successful (status 200), but the server is returning IsSuccessful=false
        alert(data.Message);//message says something like "we have that car in our catalogue but we don't have it in stock"
        return false;//early exit from .done()
    }

    //if it gets here, everything is good and I can do something with the result
})
.fail(function (data) {
    //The request actually failed due to a generic status 500 error which has something I don't necessarily want to expose in a popup to the user
    alert("Something went wrong");

});

承诺版本:

    var myPromise = Q(
    $.ajax({
        url: "/cars/1",
        type: "GET",
        contentType: "application/json; charset=utf-8",
        dataType: "json"
    })
);

myPromise.then(function (data) {
    if (!data.IsSuccessful) {
        throw new Error(data.Message);
    }

    //all good, lets do something with the result
})
.catch(function (error) {

    //what is error?
    //How do I know if it's one that I want to show to the user or not?

}).done();

在承诺版本中,如果请求返回404,它将立即在.catch()中结束吗?

如果data.IsSuccessful==false,那么它也会在.catch()

中结束

如果我想以不同的方式对待这两种失败怎么办?我该怎么做呢?

我没有在任何地方打电话或拒绝,这有问题吗?

我想确保尽可能地遵循最佳做法。

1 个答案:

答案 0 :(得分:3)

TL; DR:可以使用rejections for control flow,但一般情况下它们适用于exceptional cases only

  

在promise版本中,如果请求返回404,它会立即在.catch()中结束吗?

  

如果data.IsSuccessful == false,那么它也会以.catch()结尾?

  

我没有在任何地方打电话或拒绝,这有问题吗?

完全没有。你没有使用Promise构造函数(你不需要它,因为你已经有了ajax结果的承诺)。

  

如果我想以不同的方式对待这两种失败怎么办?我该怎么做呢?

抛出不同类型的错误,以便您可以区分它们。给他们起名字,添加特殊属性,做子类化(特别是在ES6中),或者只看消息。

  

有了承诺,如果来自.then(),我想做类似的事情,我一直认为我应该做的是抛出错误

不一定。你可以像没有承诺那样完全一样 - 在回调中添加一个if-else(或者如果你愿意,可以提前返回)。

就控制流量及其结果值而言,

.then(function(res) {
    if (!res.isOK) {
        // do something
        return false;
    }
    // do something else
}).catch(function(err) {
    // handle something
})

.then(function(res) {
     if (!res.isOK)
         throw new MyError(res);
     // do something else
}).catch(function(err) {
     if (err instanceof MyError) {
         // do something
         return false;
     }
     // handle something
})

几乎相同(除了do something中的异常以及除了抛出MyError之外的代码)。主要区别在于您希望在.then(…)then之间链接其他catch次调用。如果你不这样做,只需选择你喜欢的任何东西。