-2

kindly please help me with task. i have to convert this logic by using promises

loadUsers(userIds, load, done) {
   const users = [];
     let numberOfLoadedUsers = 0;
     userIds.forEach((userId, index) =>
       load(userId, function (user) {
         users[index] = user;
         numberOfLoadedUsers += 1;
         if (numberOfLoadedUsers === userIds.length) {
           done(users);
         }
      })
    ); 
 }
 module.exports = loadUsers;
  • i dont think so it resolve my issue . i am very new to nodejs. we are not using any APIs right – Rajesh Karasala Mar 10 '22 at 13:31
  • There's no "async loop" in your question unless `load` is an async function. Can you explain what the code is meant to be doing, and what `load` does, and we might be able to help. – Andy Mar 10 '22 at 13:36
  • load: a Function used to load user objects. Expects a numeric id and a callback. The callback will be called with the result of loading the user with the specified id (either a user object or null). * done: a Function that expects an Array of user objects (as retrieved from `load`) – Rajesh Karasala Mar 10 '22 at 13:51

1 Answers1

1

I believe what you want is to change the callback in load() to a Promise based API. While changing load() to use promises is rather simple, there are some others changes in your code necessary to make that work as you would expect it to work some of which are described in this blog post. See this version using promises and some explanatory comments.

async function loadUsers(userIds, load, done) {
    const users = [];
    let numberOfLoadedUsers = 0;
    // in order to use await in callback function must be "async"
    // now you must change from "forEach" to "map" as every callback now returns a promise and forEach does not return anything
    const promises = userIds.map(async (userId, index) => {
        const user = await load(userId);
        users[index] = user;
        numberOfLoadedUsers += 1;
        // to show you it is working
        console.log(user, index);
        if (numberOfLoadedUsers === userIds.length) {
            done(users);
        }
    });

    // promises is now an array of promises (one for each item)
    // you must wait until all promises resolve and can then return
    await Promise.all(promises);
    console.log("all users loaded.")
}

// POJ(S)O
class User {
    constructor(id, name) {
        this._id = id;
        this._name = name;
    }
}

async function load(userId) {
    // you must return a Promise in order to make it an asynchronous function
    return new Promise((resolve, reject) => {
        try {
            // load your user here (e.g. HTTP request, read from file etc.)
            const loadedUser = new User(userId, `Testuser-${userId}`)
            // user was successfully loaded -> resolve promise
            resolve(loadedUser)
        } catch (error) {
            // some error occured -> reject promise
            reject(error)
        }
    })
}

function done(){
    console.log("done() called");
}


const userIds = [1, 2, 3];
// test
(async () => {
    await loadUsers(userIds, load, done)
})();

Expected output:

User { _id: 1, _name: 'Testuser-1' } 0
User { _id: 2, _name: 'Testuser-2' } 1
User { _id: 3, _name: 'Testuser-3' } 2
done() called
all users loaded.
Mushroomator
  • 6,516
  • 1
  • 10
  • 27
  • I need to see Promise.all(...).then(done) at the end. You have to complete the remaining part. please i need this – Rajesh Karasala Mar 11 '22 at 08:33
  • I don't understand. What is missing? You can just call `done()` after `await Promise.all(promises)`. But you are calling `done()` after loading the last user anyway using the `if` condition (which you actually do not need at all as you can just await `Promise.all(...)`) – Mushroomator Mar 11 '22 at 10:12