0

I want to do something simple: I want my function to return a promise(1). This promise(1) will use another promise(2) to perform a task. Promise(2) is chained to multiple then/catch steps. Inside those steps, promise(1) may need to be resolved/rejected. The chain of promise(2) needs to stop executing as now promise(1) is resolved/rejected and should stop running.

What's the best way to do this?

See the following example code:

function performDiv(a, b) {
    return new Promise(function (res, rej) { // promise(2)
        if (b === 0) {
            return rej(new Error('div by 0'));
        }
        res(a / b);
    })
}

function div(a, b) {
    return new Promise(function (res, rej) { // promise(1)
        performDiv(a, b)
        .then(res) // <--- HERE I want to break the chain
        .catch(rej) // <--- OR HERE, if there's a problem
        .then(function () {
            console.log('I don\'t want this to be shown')
        });
    });
}

div(10, 2)
.then(function (result) {
    console.log(result);
})
.catch(function (err) {
    console.log(err);
});

Currently, the I don't want this to be shown (a hypothetical next step in order to resolve the promise(1)) is shown while I want to find a solution where it isn't, as the promise(1) is already resolved/rejected.

hytromo
  • 1,501
  • 2
  • 27
  • 57
  • Nothing shown is asynchronous. Why do you need promises for this at all? – charlietfl Mar 11 '17 at 13:13
  • Just remove the `then` with `'I don't want this to be shown'`. This is not a joke. If you have already resolved/rejected promise one (I am not even taking about the wrong approach with nested promises here), then why add something you want to never execute? If this is a *hypothetical step to resolve promise(1)*, then you are missing the point. You cannot get there without promise 1 already having been resolved or rejected. That is the whole idea behind `then` – trincot Mar 11 '17 at 13:32
  • Guys you missed the point, and I'm maybe the one to blame. Suppose that the chain has some if/then that `may` or `may not` resolve the promise(1). If the only do sth that doesn't resolve/reject the promise, then the chain may continue. The synchronous code is just an example. – hytromo Mar 11 '17 at 14:48
  • Also, it seems pretty physical to me that a promise can be rejected before the chain finishes. How can I reject the promise and disrupt the chain? – hytromo Mar 11 '17 at 14:53
  • You could try [conditional code in a promise chain](http://stackoverflow.com/a/36438164/918910). Also, you're using [`catch` to resume](http://stackoverflow.com/a/30741722/918910) which seems wrong given what you say you want. You might also consider `Promise.race`, even though it doesn't actually stop the other chain. – jib Mar 12 '17 at 14:16
  • Also, please avoid the [promise constructor anti-pattern](http://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it), and [return all promises](http://stackoverflow.com/a/37084467/918910). – jib Mar 12 '17 at 14:23

1 Answers1

0

I think the problem here is misunderstanding of how a promise work.

Only way to break the promise chain is to throw an error and not catch it as until end.

Let's take your example.

function div(a, b) {
    return new Promise(function (res, rej) { // promise(1)
        performDiv(a, b)
        .then(res) // <--- HERE I want to break the chain (A)
        .catch(rej) // <--- OR HERE, if there's a problem (B)
        .then(function () { // (C)
            console.log('I don\'t want this to be shown')
        });
    });
}

Both A & B could throw an error to break the chain of then-ables.

If (A) throws an error B will catch it. In B you are calling reject function, which sets Promise 1 as rejected, however it continues to execute remaining chain on Promise 2, because, rej method returns a value (it could be undefined), which makes that promise (the one catch returns) to resolve.

Take away: each then or catch themselves returns a Promise. To break the chain throw an error and do not catch it until the end.

Arun Karunagath
  • 1,593
  • 10
  • 24