Using Kris Kowal's Q. How should I catch if any errors have been thrown throughout the life of a chained promise?

StackOverflow https://stackoverflow.com/questions/23123202

質問

I'm new to promises, and I just started using Kris Kowal's Q today (I've read about it before and used it a little with Angular.js), and I was doing an Ajax call with jQuery and turning it into a Q promise. I was trying to find a good way to have some sort of catch at the end that would tell me whether this promise was rejected at one point or not so I could tell the user something went wrong along the way.

The idea is I want to extend the idea to work no matter how long my promise and at the end I want a check to see if it failed at anytime during the promise. This is what I ended up writing, but I wouldn't want to throw a new error in each of my fails/catches like this in order to propogate the error down the promise chain. I want something less weird.

function deleteEvent(id){
    var url = "sampleURL/deleteEvent?id=" + id;
    return Q($.ajax({
        type: 'POST',
        url: url,
        dataType: 'json'
    })).then(function (data) { // success
        // on success
        UpdateDOMforEventsChanged();
    }).fail(function (xhr) { // failure
        console.log(xhr);
        throw new Error('Problem deleting Event');
    });
}

And here's how I extended this promise elsewhere

deleteEvent(event._id).then(function () { // AJAX call was a success delete the things
    $('#calendar').fullCalendar('removeEvents', event._id);
}).done(null, function () { // It failed somewhere alert the user.
    alert("There was an error with deleting the event. Check your network connection and try again.")
});

So basically I've noticed that if I take out the error that I'm throwing in the fail section of my deleteEvent promise that it executes the following then that comes after it in the extended promise i.e. it executes deleting the events client side from fullCalendar. I don't want it to do this if it fails, how can I fix this? Also is there a reason why it does this? I'm guessing it might be, because you can resolve the error somehow or set a default and continue the promise chain...is that right?

I also notice if I don't throw the error it skips over the fail callback function of the done method. I know this is because the q documentation says the following about it's .done() method,

If there is an unhandled rejection, either because promise is rejected and no onRejected callback was provided, or because onFulfilled or onRejected threw an error or returned a rejected promise, the resulting rejection reason is thrown as an exception in a future turn of the event loop.

So I'm assuming I can't use .done() to catch all rejections including handled ones, (and I'm guessing in the ajax error is handled since I have the catch/fail after it), but what alternative is there?

役に立ちましたか?

解決 2

If you don't throw in fail it means you recover from error to success (see: Rejection into success [use cursors] mind fail is alias for catch), so result promise ends as successful. It can't be other way

Instead of using fail see if Q provides function which provides access to result and returns self promise (something like aside in implementation I mantain).

Also your flow can be simpler with less then's, see:

function deleteEvent(id) {
    return Q($.ajax({
        ....
    })).then(function (data) { // success
       // on success
       UpdateDOMforEventsChanged();
    }); // No need for error handler
};

deleteEvent(event._id).done(function () { // AJAX call was a success delete the things
    $('#calendar').fullCalendar('removeEvents', event._id);
}, , function (e) { // It failed somewhere alert the user.
    console.error(e.stack || e.message);
    alert("There was an error with deleting the event. Check your network connection and try again.")
});

他のヒント

A handled rejection is like a caught exception. It stops propagating since well, it was handled. If you want to handle the rejection and keep it rejected you need to rethrow, again, just like in synchronous code.

   try {
       throw new Error();
    } catch(e){
        // handle error   
    }
    // no error here this code will keep running.

If you want it to keep rejecting and handle it, you need to rethrow:

   try {
       throw new Error();
    } catch(e){
        // handle error   
        throw e;
    }
    // this code will not run

The same with promises, just like you wrote. This is not particularly odd about promises, this is how synchronous exceptions work as well. If you want to propagate - you re-throw, otherwise - the errors are considered handled.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top