Search code examples
javascriptexceptionpromisecatch-block

Promise data and exception handling


I am confused with the use of promise, specifically of its way of data manipulation (passing values from block to block) and exception handling (bubbling up the error). I am trying to learn a right way to use promise and to handle error, something like

Error: A caught error.
    at promiseTwo()
    at promiseOne()
    at subprocess()
    at mainprocess()

Here are my two attempts in implementing them:

Attempt 1: Clumsy, deeply nested, and errors are uncaught.

var subprocess = () => {
    return new Promise((resolve, reject) => {
        promiseOne().then(data1 => {
            // Some code with data1, throw some error
            promiseTwo().then(data2 => {
                // Some code with data1n2, throw some error
                promiseThree().then(data3 => {
                    // Data manipulation with data1, data2, and data3
                    return resolve(<...>)
                }).catch(err3 => { throw err3 })
            }.catch(err2n3 => { throw err2n3 })          // >>> ERR: Cannot get err3.
        }.catch(err1n2n3 => { return reject(err1n2n3) }) // >>> ERR: Cannot get err3 or err2.
    }
}

return new Promise((resolve, reject) => {
    subprocess().then(data => {
        // TODO
    }).catch(allErr => { return reject(allErr) }
}

Attempt 2: Unable to use data from previous promise block.

var subprocess = () => {
    return new Promise((resolve, reject) => {
        promiseOne()
        .then(data1 => {
            // Some code with data1, throw some error
            return promiseTwo()
        })
        .then(data2 => {
            // Some code with data1n2, throw some error
            // >>> ERR: Cannot get data1
            return promiseThree()
        })
        .then(data3 => {
            // Data manipulation with data1, data2, and data3
            // >>> ERR: Cannot get data1 and data2
            return resolve(<...>)
        })
        .catch(err1n2n3 => { 
            return reject(err1n2n3) 
        })
    }
}

return new Promise((resolve, reject) => {
    subprocess().then(data => {
        // Some code, throw some error
    }).catch(allErr => { return reject(allErr) }
}

Note: Some of the promise block (i.e. promiseOne, promiseTwo, etc.) are pre-defined so I do not have control over what data they will return. I am sure there are more errors in the attempts (e.g. if returning a function is a right way to do it).

Please help. Thanks.


Solution

  • for this kind of situation, you can combine promises and async-await together.

    From the question, it seems we have three promises and one function that executes and handle them.

    You can try something like this -

    const subProcess = () => {
      return new Promise((resolve, reject) => {
        // Using IIFE ( You shouldn't put async keyword on promise callbac )
        (async () => {
          // Use of try catch to handle the errors
          try { 
            await promiseOne()
            await promiseTwo()
            await promiseThree()
            // Additional code if need after them
          } catch(err){
            // Handle error ( all three promise error will be transferred here )
          }
        })()
    
      })
    }
    

    The above code waits for the promises to execute one by one and also catch error from all three promises if any.

    And as @samuei mentioned, you can also use Promise.all() in this.

    const subProcess = () => {
      return new Promise((resolve, reject) => {
        // Using IIFE ( You shouldn't put async keyword on promise callbac )
        (async () => {
          // Use of try catch to handle the errors
          try { 
            const myPromises = [promiseOne, promiseTwo, promiseThree];
            const res = await Promise.all(myPromises);
            // Additional code if need after them
          } catch(err){
            // Handle error ( all three promise error will be transferred here )
          }
        })()
    
      })
    }
    

    And if you don't want to use async-await then you can do something like this as well

    const subProcess = () => {
      return new Promise((resolve, reject) => {
        const myPromises = [];
        const myPromises = [promiseOne, promiseTwo, promiseThree];
    
        Promise.all(myPromises)
        .then(res => {
          // Handle the response
        })
        .catch(err => {
          // Handle the error
        })
    
      })
    }