2
votes

I have a .then in a promise return, and in that I have defined an async function that gets some data from an API. The part where I am stuck is that when I throw an error (Forcefully), it is not caught by the catch block.

From what I have learnt, a single .catch is enough for all the .then statements. Is this because there's another async function inside the code and hence the .catch is not working?

CampaignController.getOnboardingCampaignList = (req,res) => {

    return OnBoardingCampaign.find({description : {$exists : true}},{name: 1, description : 1, suggestedHaikuIds : 1})
    .then((r) => {
      // Some Logic here, unrelated the the work done below

        async function getSuggestedHaiku(){
            for(const campaign of r ){
                let suggestedHaikuIds = [];
                campaign.suggestedHaikus = [];
                throw new Error; // Using this to throw the new error
                if(campaign.suggestedHaikuIds === '') campaign.suggestedHaikuIds = [];
                else{
                    campaign.suggestedHaikuIds.forEach((id) => {
                        suggestedHaikuIds.push(Helper.parseId(id))
                    }) // This particular line threw the error initially
                    const result = await SuggestedHaiku.find({_id: {$in : suggestedHaikuIds}},{timeStamp : 0, deleted : 0, returnCount : 0, writtenCount : 0});

                    campaign.suggestedHaikus = result;
                }

            }

            if(r.length === 0){
                return Promise.reject(1001);
            }else{
                let result = {};
                result.list = r;
                Helper.success(res,"Onboarding Campaign List",result);
            }
        }
        getSuggestedHaiku();    


    })
    .catch(err => Helper.error(res, err)) // This catch did not catch the error thrown above

}

The error messages are as follows

UnhandledPromiseRejectionWarning: Error at getSuggestedHaiku (/Users/abhinav/haikuserver/controllers/campaign.js:242:23) at OnBoardingCampaign.find.then (/Users/abhinav/haikuserver/controllers/campaign.js:263:9) at process._tickCallback (internal/process/next_tick.js:68:7) warning.js:18 (node:7646) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2) warning.js:18 (node:7646) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

2
if you return getSuggestedHaiku(); it will - because Promises work that wayJaromanda X
You're mixing promises with async/await. It makes the code less readable and harder to maintain. Advice: choose one way and stick with it!Nir Alfasi
@JaromandaX Your solution works, could you please point me out to a resource from where I can learn more about it.Clarskon
I find MDN documentation pretty informativeJaromanda X

2 Answers

1
votes

Try catch should be wrapped to for loop.

try{

      for(const campaign of r ){}

}catch() {}
0
votes

Javascript executes commands without necessarily waiting for the previous functions / commands to complete. By the time your async function gets completed and throws an error, the flow of control has already moved ahead of the catch block.

Hence, by the time an error / promise-rejection occurs, there is no catch-block remaining in the event loop to handle it.