mpc75
mpc75

Reputation: 989

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();

Upvotes: 0

Views: 47

Answers (2)

Roamer-1888
Roamer-1888

Reputation: 19288

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();

Upvotes: 3

Bergi
Bergi

Reputation: 664548

The problem is that your recursive hello(++index, i) call is ignored - you never use its result value. It might be a rejected promise (for which you then get the "unhandled rejection" warning), and worse, you never resolve the promise you are constructing. But you should avoid the Promise constructor antipattern anyway!

async function hello(index, i) {
    console.log(`index is ${index} and loop is ${i}`)
    if (index === 5) {
        throw new Error(`${index} is too many errors`)
    } else if (index === 6) {
        return "I realize it won't ever resolve :)"
    } else {
        return hello(++index, i)
//      ^^^^^^ this is essential! Or at least `await` the returned promise
    }
}

async function loop() {
    for (var i = 0; i <= 35; i += 7) {
        try {
            await hello(0, i)
        } catch(err) {
            console.log("caught an error!", err)
        }
    }
    console.log("resolved everything")
}

loop().then(() => {
    console.log("loop_function complete")
}, () => {
    console.log("unhandled error")
})

Upvotes: 1

Related Questions