4

I am trying to stop a promise chain midway (After a catch). So after an error occurred in the first promise the catch will catch it but I don't want the chain to continue. I'm using bluebird. How would I do this?

getRedirectedURL(url).then(function(url) {
                console.log(1);
                url = domainCleanse(url);
                sql = mysql.format(select, url);

                return [ url, mysqlQuery(sql) ];

            }).catch(function(error) {
                console.log(2);
                console.error(error);
                socket.emit('error:unreachable', url + ' was unreachable');
            }).spread(function(url, rows) {
                console.log(3);
                if(_.isEmpty(rows[0])) {
                    socketList.push({
                        url: url,
                        ttl: _.now(),
                        socket: socket,
                        added: false
                    });
                } else {
                    socket.emit('done', mapResults(rows[0]));
                }
            }).catch(function(error) {
                console.log(4);
                console.error(error);
                socket.emit('error', 'We could not reach ' + url + ' at this time.');
            });
peterh
  • 11,875
  • 18
  • 85
  • 108
user2072912
  • 275
  • 1
  • 3
  • 8
  • possible duplicate of [Handling multiple catches in promise chain](http://stackoverflow.com/questions/26076511/handling-multiple-catches-in-promise-chain) – Bergi Nov 02 '14 at 17:25
  • maybe also see [Break promise chain and call a function based on the step in the chain where it is broken](http://stackoverflow.com/q/20714460/1048572) – Bergi Nov 02 '14 at 17:25

1 Answers1

3

Generalizing your example, it looks like this:

promiseToFoo()
    .then(promiseToBar)
    .catch(failedToFooOrBar)
    .then(promiseToFrob)
    .catch(failedToFrob)

Along the happy path you are promising to Foo, then to Bar, then to Frob. Based on your description, you want to handle errors Fooing or Barring separately from errors Frobbing. So a simple solution is bury the error handling for Frob into that promise. So instead of chaining a promise to Frob, you're chaining a promise to Frob and handle errors in Frobbing. Something like this:

promiseToFoo()
    .then(promiseToBar)
    .catch(function (error) {
        failedToFooOrBar(error);
        return Promise.reject(error);
    })
    .then(function (x) {
        return promiseToFrob(x).catch(failedToFrob);
    });

A key to this is to make sure that your on-reject handler in the first catch ends up leaving the chain in a rejected state when it leaves. This is handled in the sample above by returning a rejected Promise from the handler. You can also handle it by throwing an Error from the handler. If you don't do one of these things, then the promise will be in a fulfilled state when the handler finishes and the on-fulfill handler provided by the subsequent then call will be invoked.

Julian
  • 8,808
  • 8
  • 51
  • 90
brianmearns
  • 9,581
  • 10
  • 52
  • 79