我正在尝试用正确的方法表示正确的方法,以指示内发生故障.then()。
.then()
如果诺言没有失败,(即返回诺言的操作是否正常工作,例如返回状态200的AJAX请求),但是我认为结果无效,通常我会这样做弹出窗口,向用户说明问题,然后执行“返回假”;尽早退出该方法。
但是,有了承诺,如果我想从.then()内部做类似的事情,我就被引导去相信我应该做的是抛出一个错误,而应该让它被.catch()抓住。 ),我已经锁定了。
我担心的是,我想区分承诺中成功但不满意结果的操作与承诺中失败的操作。
例如,如果我执行一个AJAX调用,但失败并显示404,则该错误实际上无法恢复,因此似乎应该通过弹出窗口拒绝诸如“出事了”之类的消息来拒绝。
但是,如果AJAX请求成功(返回状态200),但响应指示某些错误(例如用户未使用正确的值填写字段),那么我想处理该问题以某种方式,可能不仅涉及带有消息的弹出窗口(例如,DOM操作,红色文本等,如果是404,我可能不想做的事情)。
以下是两个示例,可以更好地解释我的意思。
第一个是带有回调的原始实现,第二个是带有promise(将Ajax调用与Q promise库包装在一起以使其成为正确的promise)。
回调版本:
$.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版本中,如果请求返回404,它将.catch()立即结束吗?
.catch()
如果data.IsSuccessful==false是的话,它也将最终以.catch()?
data.IsSuccessful==false
如果我想以不同的方式对待这两种失败,该怎么办?
我不在任何地方打电话给我解决或拒绝,这有问题吗?
我想确保我尽可能遵循最佳实践。
TL; DR: 您 可以 将拒绝用于控制流,但通常,它们仅用于特殊情况
在Promise版本中,如果请求返回404,它将立即以.catch()结尾,对吗?
是。
如果data.IsSuccessful == false,那么它也将以.catch()结尾?
一点也不。您没有使用Promise构造函数(不需要,因为您已经有了对ajax结果的承诺)。
Promise
引发各种错误,以便您可以区分它们。给它们命名,添加特殊属性,进行子类化(尤其是在ES6中),或仅查看消息。
承诺,如果从.then()内部,我想做类似的事情,我一直认为我应该做的是抛出一个错误,而不是
不必要。您可以做与不做承诺时完全相同的操作-在回调中添加if-else(如果愿意,可以在返回时返回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此throw之外MyError的代码中的异常以及带有此类异常的代码)。主要区别在于何时要.then(…)在then和之间链接其他调用catch。如果不这样做,请选择更喜欢的选项。
do something
MyError
.then(…)
then
catch