Gleichmut
Gleichmut

Reputation: 7009

Processing errors in promises

I try to figure out how to proper handle errors in promise chain. There are few promises and one of them throws error. In case of error I would like to terminate function in chain.

The issues I faced with are:

  1. How can we terminate next call from catch block?
  2. How to guarantee execution order then().catch().then() chain? At this moment I observe catch block is called after execution of both then() functions.

Code sample:

function run() {
    test().then(function(data) {
        console.log("w3", "Print data: " + data);
    });
}

function test() {
    return new Promise(function(fulfill, reject) {
        ask()
            .catch(err => console.log("w3", "Process error from ask: " + err))
            .then(reply())
            .catch(err => console.log("w3", "Process error from reply: " + err))
            .then(function(data) {
                console.log("w3", "Finish test");
                fulfill(data);
                // TODO finish data
            })
    });
}

function ask() {
    return new Promise(function(fulfill, reject) {
        console.log("w3", "ask");   
        // fulfill("Hello");
        reject("Cancel Hello");
    });
}

function reply() {
    return new Promise(function(fulfill, reject) {
        console.log("w3", "reply");
        fulfill("World!");
        // reject("Cancel World");
    });
}

Upvotes: 0

Views: 99

Answers (2)

JamesENL
JamesENL

Reputation: 6540

That's not how Promise chains work. Promises will only chain correctly if you explicitly return a Promise out of every function invoked in your .then() blocks. If you don't return a Promise out of these functions, the next .then() block is immediately invoked.

You probably want to do something like this:

function run() {
    test()
        .then(function (data) {
            console.log("w3", "Print data: " + data);
        });
}

function test() {
    return ask()
        .then(function (result) {
            return reply();
        })
        .then(function (data) {
            console.log("w3", "Finish test");
            return Promise.resolve(data);
        })
        .catch(function (error) {
            console.log("Hey an error was thrown from somewhere");
            if(error instanceof UnexpectedAskError) {
                //handle specific error logic here. 
            }
        });
}

function ask() {
    console.log("w3", "ask");
    return Promise.reject(new UnexpectedAskError("Ask threw an error"));
}

function reply() {
    console.log("w3", "reply");
    return Promise.resolve("World!");
}

Notice how the ask function returns a specific type of error? You can do something like that if you need to perform different error handling based on which function threw an error.

To specifically answer the questions you asked:

  1. The above method of chaining promises will prevent the next .then() being called if an error is thrown by the previous function.
  2. The above method of chaining will ensure that your .then() blocks are called in the order specified. As long as every .then() is a function, and every function returns a Promise, either through constructing a new Promise(function(resolve, reject)) or through Promise.resolve or Promise.reject, the chain will execute in the correct order.

Upvotes: 2

Dat Tran
Dat Tran

Reputation: 1586

You just catch at the end of the chain. If there's any error. It will ignore the other then and go direct to catch.

function test() {
    return new Promise(function(fulfill, reject) {
        ask()
            .then(reply())
            .then(function(data) {
                console.log("w3", "Finish test");
                return fulfill(data); // <= Make sure to return here
                // TODO finish data
            })
            .catch(err => console.log("w3", "Process error from reply: " + err))
    });
}

Make sure to return Promise or else it won't catch your error.

fulfill(data); should be return fulfill(data);

Upvotes: 1

Related Questions