Search code examples
node.jspromiseasync-awaites6-promise

How do I get my program to keep running when a single promise resolves or rejects?


I want my program to resolve if everything worked and then go onto the next test using a for loop; or, if there is an error, I want it to run again. But if it hits an error six times, I want it to give up and try the next function with the loop.

What I expect:

index is 0 and loop is 0
index is 1 and loop is 0
index is 2 and loop is 0
index is 3 and loop is 0
index is 4 and loop is 0
index is 5 and loop is 0
5 is too many errors
[printed error]
index is 0 and loop is 7
index is 1 and loop is 7
index is 2 and loop is 7
index is 3 and loop is 7
index is 4 and loop is 7
index is 5 and loop is 7
5 is too many errors
[printed error] ..  and so on

What I actually get:

index is 0 and loop is 0
index is 1 and loop is 0
index is 2 and loop is 0
index is 3 and loop is 0
index is 4 and loop is 0
index is 5 and loop is 0
5 is too many errors
(node:29808) UnhandledPromiseRejectionWarning: undefined
(node:29808) UnhandledPromiseRejectionWarning: Unhandled promise rejection.

The code:

const hello = async (index, i) => {
  return new Promise(async (resolve, reject) => {
        console.log(`index is ${index} and loop is ${i}`)
        if(index === 5){
            reject(console.log(`${index} is too many errors`)) // this runs
        } else if (index === 6){
            resolve(console.log("I realize it won't ever resolve :) ")) 
        }
        else{
            hello(++index, i)
        }
    })
};

const loop_function = async () => {
    return new Promise (async(res, rej)=>{
        for (var i = 0; i <= 35; i += 7) {
            try{
                await hello(0, i)
            } catch(err){
                console.log("caught an error!") // this does not run
            }
        }
        res(console.log("resolved everything")) // this does not run
    })
}


const final = async () =>{
    await loop_function()
    console.log("loop_function complete") // this does not run
}


final();

Solution

  • Things to amend:

    1. purge the new Promise() wrappers from both functions; they are unnecessary as AsyncFunctions are guaranteed to return Promise and internally you can simply return/throw.
    2. be sure to return hello(++index, i) in order to return the outcome of each level of the recursion to its superior levels, and eventually to the original caller at the topmost level.
    3. when the (index >= 5) condition is met, simply throw an Error; there's no need to log as the caller's (loop_function's) catch block will do the logging.

    So, you might end up with :

    const hello = async (index, i) => {
    	console.log(`index is ${index} and loop is ${i}`);
    	if(index >= 5) {
    		throw new Error(`${index} is too many errors`);
    	} else {
    		return hello(++index, i);
    	}
    };
    const loop_function = async () => {
    	for (var i = 0; i <= 35; i += 7) {
    		try {
    			await hello(0, i);
    		} catch(err) {
    			console.log(err.message);
    		}
    	}
    	console.log("resolved everything");
    }
    const final = async () =>{
    	await loop_function();
    	console.log("loop_function complete");
    }
    final();