How to stop code within nested callbacks and a foreach loop?

so currently I’m setting up a little nodejs database and I’m basically trying to get all user info (if the user exists) and do a callback returning the user’s info, if the user doesn’t exist then I return null. Basically my issue here is that when I do return callback(null) or return callback(userdata) return doesn’t stop code execution, resulting in 2 executions of the callback and invalid data. It could be due to the various callbacks that these return callback()‘s are nested in or the foreach loop, although if it is, I’m not sure how to fix it. Any help is greatly appreciated, thank you!

Here is the code:

const getUserInfo = (sessionToken, callback) => {
    return fs.readdir(__dirname + "/database/users", (err, files) => {
        if(err) return callback(null);
        return files.forEach((file, index) => {
            return fs.readFile(__dirname + "/database/users/" + file, "UTF-8", (err, data) => {
                if(err) return callback(null);
                try {
                    const parsedData = JSON.parse(data);

                    if(parsedData.sessionToken === sessionToken) return callback({ email: parsedData.email, username: parsedData.username, bought: parsedData.bought });
                    else if(index === files.length - 1) return callback(null);
                } catch {
                    return callback(null);
                }
            });
        });
    });
}

A little explanation for the code: this is a function that takes in a sessionToken, which is a random string of characters for the user’s current session, and a callback of course. It then reads the database/users directory to get all the users, then for every user in that directory it reads the file and try’s to parse the data through JSON, if it doesn’t work then of course it returns null, if it does work and the sessionToken matches then it executes the callback with all the necessary user information. If we get to the end of the list and none of the sessions matched then we come to the conclusion the user doesn’t exist.

4 thoughts on “How to stop code within nested callbacks and a foreach loop?”

  1. Don’t use a .forEach() loop. Use a plain for loop instead. .forEach() provides NO way to stop the loop. When you return from the .forEach() loop, you’re just returning from the callback function, not returning from the parent function so there’s no way to stop the loop or return from the parent function from within the .forEach() loop.

    Using a regular for loop, you can either break or return to stop the loop.

    In addition, since you’re doing an asynchronous operation inside the loop, you also will need to use let data = await fs.promises.readFile() (and make the parent function async) in order to sequence your file reads one after the other. Without that, all your read operations will proceed in parallel and you will have no control over the order of completion. And, one you do that, you may as well return a promise from your function with the results, rather than use a plain callback function.

    Reply

Leave a Comment