拒绝 Javascript 承诺和错误处理
Rejecting Javascript Promises And Error Handling
我正在努力思考在 .then()
中指示失败的正确方法。
如果承诺没有失败,(即 returns 承诺正确完成工作的操作,例如 AJAX 请求 returns 状态 200) ,但我认为结果无效,通常我会弹出一个窗口,向用户解释问题,然后执行 "return false;" 提前退出该方法。
然而,有了承诺,如果在 .then() 中,我想做类似的事情,我被引导相信我应该做的是抛出一个错误,并且大概让这个被捕获通过我链接的 .catch()。
我担心的是,我想区分成功但我不喜欢其结果的 promise 操作和失败的 promise 操作。
例如,如果我执行一个 AJAX 调用并且它失败并显示 404,那实际上是不可恢复的,因此用一个弹出窗口说 "something went wrong" 之类的内容来拒绝似乎是合适的。
但是,如果 AJAX 请求成功(returns 状态 200),但响应表明有问题(比如用户没有填写字段一个正确的值),然后我想以某种方式处理它,这可能不仅涉及带有消息的弹出窗口(例如,可能 DOM 操作,红色文本等,我可能不想做的事情如果这是一个 404)。
下面有 2 个例子可以更好地解释我的意思。
第一个是带有回调的原始实现,第二个是带有承诺的(使用 Q 承诺库包装 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();
在 promise 版本中,如果请求 returns 一个 404 它将立即在 .catch()
中结束,对吗?
如果data.IsSuccessful==false
,那么它也会在.catch()
?
中结束
如果我想以不同的方式对待这两种失败,我会怎么做?
我不是在任何地方调用 resolve 或 reject,这有问题吗?
我想确保我尽可能遵循最佳做法。
TL;DR: 你可以使用rejections for control flow, but in general they are for exceptional cases only
In the promise version, if the request returns a 404 it will end up in the .catch() immediately right?
是的。
If data.IsSuccessful==false, then it will also end up in the .catch()?
是的。
I'm not calling resolve or reject anywhere, is that problematic?
完全没有。您没有使用 Promise
构造函数(您不需要它,因为您已经对 ajax 结果做出了承诺)。
What if I want to treat both failures differently, how would I go about that?
抛出不同类型的错误,以便您区分它们。给它们命名,添加特殊属性,进行子类化(尤其是在 ES6 中),或者只是查看消息。
with promises, if from within the .then(), I want to do something similar, I've been lead to believe that what I should do is throw an error instead
不一定。您可以像没有 promises 的情况下那样做 - 在回调中放置一个 if-else(或者如果您愿意,可以在早期 return 中放置一个 if)。
在控制流及其结果值方面,
.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
和 catch
之间链接额外的 .then(…)
调用时。如果你不喜欢,就选择你更喜欢的。
我正在努力思考在 .then()
中指示失败的正确方法。
如果承诺没有失败,(即 returns 承诺正确完成工作的操作,例如 AJAX 请求 returns 状态 200) ,但我认为结果无效,通常我会弹出一个窗口,向用户解释问题,然后执行 "return false;" 提前退出该方法。
然而,有了承诺,如果在 .then() 中,我想做类似的事情,我被引导相信我应该做的是抛出一个错误,并且大概让这个被捕获通过我链接的 .catch()。
我担心的是,我想区分成功但我不喜欢其结果的 promise 操作和失败的 promise 操作。
例如,如果我执行一个 AJAX 调用并且它失败并显示 404,那实际上是不可恢复的,因此用一个弹出窗口说 "something went wrong" 之类的内容来拒绝似乎是合适的。
但是,如果 AJAX 请求成功(returns 状态 200),但响应表明有问题(比如用户没有填写字段一个正确的值),然后我想以某种方式处理它,这可能不仅涉及带有消息的弹出窗口(例如,可能 DOM 操作,红色文本等,我可能不想做的事情如果这是一个 404)。
下面有 2 个例子可以更好地解释我的意思。
第一个是带有回调的原始实现,第二个是带有承诺的(使用 Q 承诺库包装 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();
在 promise 版本中,如果请求 returns 一个 404 它将立即在 .catch()
中结束,对吗?
如果data.IsSuccessful==false
,那么它也会在.catch()
?
如果我想以不同的方式对待这两种失败,我会怎么做?
我不是在任何地方调用 resolve 或 reject,这有问题吗?
我想确保我尽可能遵循最佳做法。
TL;DR: 你可以使用rejections for control flow, but in general they are for exceptional cases only
In the promise version, if the request returns a 404 it will end up in the .catch() immediately right?
是的。
If data.IsSuccessful==false, then it will also end up in the .catch()?
是的。
I'm not calling resolve or reject anywhere, is that problematic?
完全没有。您没有使用 Promise
构造函数(您不需要它,因为您已经对 ajax 结果做出了承诺)。
What if I want to treat both failures differently, how would I go about that?
抛出不同类型的错误,以便您区分它们。给它们命名,添加特殊属性,进行子类化(尤其是在 ES6 中),或者只是查看消息。
with promises, if from within the .then(), I want to do something similar, I've been lead to believe that what I should do is throw an error instead
不一定。您可以像没有 promises 的情况下那样做 - 在回调中放置一个 if-else(或者如果您愿意,可以在早期 return 中放置一个 if)。
在控制流及其结果值方面,
.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
和 catch
之间链接额外的 .then(…)
调用时。如果你不喜欢,就选择你更喜欢的。