I'm trying to wrap my head around the correct way to indicate a failure within a .then()
.
If the promise doesn't fail, (I.e. the operation that returns the promise does it' job properly, such as an AJAX request that returns a status 200), but I decide that the result isn't valid, usually I'd do a popup, explaining the issue to the user, and do a "return false;" to exit the method early.
However, 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, and presumably let this get caught by the .catch() that I've chained on.
My concern is that I want to distinguish between an operation within a promise that succeeded, but which I don't like the result of, and a failed operation within a promise.
For example, if I perform an AJAX call and it fails with a 404, that's not really recoverable, so it seems appropriate to reject with a popup saying something like "something went wrong".
However, if the AJAX request is successful (returns a status 200), but the response indicates that something isn't right (Like the user didn't fill out a field with a correct value), then I'd like to handle that a certain way, which might involve not just a popup with a message (e.g. maybe DOM manipulations, red text etc, things that I might not want to do if it's a 404).
Below are 2 examples to better explain what I mean.
The first being the original implementation with callbacks and the second being with promises (Wrapping the ajax call with the Q promise library to make it a proper promise).
Callback version:
$.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");
});
Promise version:
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();
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()
?
What if I want to treat both failures differently, how would I go about that?
I'm not calling resolve or reject anywhere, is that problematic?
I'd like to make sure I'm following best practices as much as possible.
See Question&Answers more detail:
os