104

This is probably a silly question, but mid promise chain, how do you reject a promise from inside one of the then functions? For example:

someActionThatReturnsAPromise()
    .then(function(resource) {
        return modifyResource(resource)
    })
    .then(function(modifiedResource) {
        if (!isValid(modifiedResource)) {
            var validationError = getValidationError(modifiedResource);
            // fail promise with validationError
        }
    })
    .catch(function() {
        // oh noes
    });

There's no longer a reference to the original resolve/reject function or the PromiseResolver. Am I just supposed to add return Promise.reject(validationError); ?

chinabuffet
  • 5,278
  • 9
  • 40
  • 64
  • 2
    `throw validationError` – kavun Jan 21 '14 at 14:24
  • >< I had a feeling it would be something silly/easy that. Guess I kept thinking that I had to call a dedicated rejection function or return a failed Promise instead. So from inside a promise/thenable, any returned value that is not a new Promise will be considered the resolved value? And if I throw an error, that's the same as returning an immediately rejected Promise? If you post that as an answer I'll accept it. – chinabuffet Jan 21 '14 at 14:28
  • You are probably looking for the accepted answer here http://stackoverflow.com/questions/17800176/jquery-deferred-rejecting-a-promise-from-within-a-done-filter – crad Jan 21 '14 at 14:29

2 Answers2

106

Am I just supposed to add return Promise.reject(validationError);?

Yes. However, it's that complicated only in jQuery, with a Promise/A+-compliant library you also could simply

throw validationError;

So your code would then look like

someActionThatReturnsAPromise()
    .then(modifyResource)
    .then(function(modifiedResource) {
        if (!isValid(modifiedResource))
            throw getValidationError(modifiedResource);
        // else !
        return modifiedResource;
    })
    .catch(function() {
        // oh noes
    });
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 4
    Is this a regular thing to do? Is it widely used? I feel bad doing it, because if somewhere in the code `.catch` is missing, the **whole** app will blow up with unhalted error.. – Andrey Popov Feb 26 '15 at 13:33
  • 3
    Note that in a Promise/A+ compliant library you can use throw because the `handler` for `then` is sync and the exception can be catched. If the handler is async, it has to return a promise to eventually reject. So always returning Promise.reject() instead of throwing makes sense to me. Because if you throw in an async handler, the library can't catch it and it will silently pass. Beware. – Mike Gleason jr Couturier Jun 27 '15 at 15:34
  • 1
    @MikeGleasonjrCouturier: There should be no async handlers that are not `.then` handlers on a promise :-) If you're using a not promisified API, then even `return Promise.reject()` will help you. – Bergi Jun 27 '15 at 15:58
  • @Bergi I meant like: `p.then(function() { doAsync(function() { throw new Error("won't catch"); }); });` EDIT: oh okay I re-read your comment, I'm totally with you, we are on the same page! I wanted to point it out to the OP :) – Mike Gleason jr Couturier Jun 27 '15 at 16:02
  • 1
    @MikeGleasonjrCouturier: Yes, that's exactly what I was saying. And `doAsync(function() { return Promise.reject(new Error("won't catch, won't throw")); })` doesn't work there either - it just fails silently. It really should be `doAsync().then(function() { throw new Error("will be caught"); })` when you're working with promises. – Bergi Jun 27 '15 at 16:04
0

Use Promise.reject

Like this

function test()
{
    return new Promise((resolve, reject) => {
        resolve(null)
    }).then(() => console.info('yes')).then(() => {
        return Promise.reject('hek');
    })
}

test().then(() => console.info('resolved')).catch(() => console.info('rejected'))
shamaseen
  • 2,193
  • 2
  • 21
  • 35