Callback after loop completion in node.js

I need help on the asynchronous nature of node.js. I have a for loop that collects data from a database. "result" is an array that should then be returned to the main function.

user_collection.findOne({
            _id : uid
        }, function(error, user) {
            if(error)
                callback(error)
            else {
                for(var j = 0; j < user.contacts.length; j++) {
                    if(user.contacts[j].accepted == 'true') {
                        user_collection.findOne({
                            _id : user.contacts[j].contactId
                        }, function(error, user) {
                            result.push(user);
                        })
                    } 
                }
                callback(null, result);  // This callback executes before the for-loop ends, ofc
            }
        });

How can I guarantee that the callback will be executed after the loop finishes?

+5
source share
3 answers

You might want to use a helper library like async https://github.com/caolan/async

This helps keep the code more consistent.

In your case, you can look at the forEach () method

forEach(arr, iterator, callback)

An iterator is called with an item from the list and a callback when it is finished.

Unit Test Inspection for Examples

https://github.com/caolan/async/blob/master/mocha_test/each.js

+10

ES6 Promises ( ):

, (, 1, 2, 3)

function asyncFunction (item, cb) {
  setTimeout(() => {
    console.log('done with', item);
    cb();
  }, 100);
}

let requests = [1, 2, 3].reduce((promiseChain, item) => {
    return promiseChain.then(new Promise((resolve) => {
      asyncFunction(item, resolve);
    }));
}, Promise.resolve());

requests.then(() => console.log('done'))

"" (2 , 1)

let requests = [1,2,3].map((item) => {
    return new Promise((resolve) => {
      asyncFunction(item, resolve);
    });
})

Promise.all(requests).then(() => console.log('done'));

Promise.all(body.schedules.map(function(scheduleId) {
        return new Promise(function(resolve, reject) {
            return scheduleSchema.findOneAndRemove({
                    _id: scheduleId
                })
                .then(function() {
                    logSchema.insert({
                        userId: req.user.id,
                        actId: constants.LOG_SCHEDULE_DELETE.id,
                        extData: scheduleId
                    });
                    resolve();
                })
                .catch(function(err) {
                    reject(err);
                });
        });
    })).then(function() {
        return res.json({
            code: constants.SUCCESS_CODE
        });
    }).catch(function(err) {
        return res.json(constants.DATABASE_ERROR);
    });

function callback (result) { console.log('all done'); }

[1, 2, 3].forEach((item, index, array) => {
  asyncFunction(item, () => {
    if (index === array.length - 1) {
      callback();
    }
  });
});

, . , .

.

+1

v1.5.2 Async.js, each.

each(arr, iterator, [callback])

arr is an array to iterate.
iterator (element, callback) . Function applied to each element in arr. callback (err) - Optional. A callback that is called when all iterator functions are complete or an error occurs.

0
source

All Articles