Richard
Richard

Reputation: 7433

Throwing inside a catch block in a nested Promise to trigger the catch block of outer Promise, is there an alternative cleaner way?

I'm nesting Promises and I have to know whether the nested Promise is a rejected Promise or a fulfilled Promise to know whether to trigger the outer Promise chain's catch. To differentiate if the nested Promise is rejected or fulfilled, I use a throw in my nested Promise's catch to indicate rejection; while fulfillment is always indicated when there's no throw in my nested Promise's catch. Please take a look at the example below:

let test = new Promise((resolve, reject) => {
  resolve(42);
}).then((e) => {
  console.log(e);
  return new Promise((resolve, reject) => { //Error happens inside this nested Promise
    resolve(32);
  }).then((e) => {
    console.log(e);
    //Run other processes that may lead to an error
  }).catch((e) => { //I added this catch block for error detection, whatever error it might be
    console.log(e);
    throw(e); //I'm throwing (e) from the inner Promise's catch so that the returned Promise in the outer then is a rejected Promise, which will be "caught" by the catch block of the outer Promise
  });
}).catch((e) => {
  console.log(e); //I handle error that happen may either in the inner Promise or the outer Promise here
});

The above shows what I meant by throw-ing inside the catch block of my nested Promise. Is the above the standard way to indicate that a nested Promise failed, or is there an alternative cleaner method to achieve what I want? As you can see, I'm practically throw-ing twice inside my nested Promise to indicate rejection. Is there a way where I can throw once and indicate Promise rejection?

EDIT

The reasons I'm using a catch block in my inner Promise and my outer Promise: I want to detect error inside my inner Promise, and said detection is done using my inner catch block; I want to handle the error that may happen in the inner Promise or in the outer Promise with the same handler, and that is done using my outer catch block. Because catch-ing inside my inner Promise returns a Promise that is considered fulfilled to my outer Promise's then block, I decided to use throw inside my inner catch block to indicate that it actually isn't fulfilled if it reached the inner catch block. I've also edited my code to indicate that the error happening inside my inner Promise is not manually triggered by me throw-ing in the code.

Upvotes: 5

Views: 2037

Answers (2)

Edwin
Edwin

Reputation: 440

I think the clean way to do this would be using async/await. But before going there, is your question how to not run the outer promise when the inner promise fails?

The example below:

  • When the inner promise rejects, the chain stops.
  • When the outer promise rejects, the inner is already fulfilled.

const fun42 = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() =>{
            resolve(42)
            reject('something at fun 42 went wrong')
        }, 500)
    })
}

const fun32 = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() =>{
            //resolve(32)
            reject('something at fun 32 went wrong')
        }, 500)
    })
}

fun32().then(x => {
    console.log(x)
    return fun42()
}).then( y => {
    console.log(y)
}).catch (e => {
    console.log(e)
})

Upvotes: 5

tomericco
tomericco

Reputation: 1584

Well, it's a question of design. Error handling should happen in one place on each level (like you did in your example). The nested catch function handles the error the decide whether it should propagate it or quietly finish it (like your wrote).

In that specific example I would use the reject function of the wrapping Promise to reject it, other than throwing an error.

Upvotes: 2

Related Questions