This is a little long and messy code, but please bear with me because I need to get this done.
I am trying to update a json object in for each users. I want the loop iterations to wait for the asynchronous process to end in order to avoid race conditions. However, this has led to a callback hell and now I cannot decide what is the right place for each callbacks to be returned.
I referred to this answer on Nesting async.eachSeries and also tried to structure my code according to it. But still it does not work. The code gives callback already called error at callback1().
async.eachOfSeries(res, function (value, camp, callback3) { let _id = res[camp]._id; let arr = res[camp].campaignID; async.eachOfSeries(arr, function2, function (err) { callback3(); }) function function2(value1, i, callback2) { let users = arr[i].users; let id = arr[i].id; let loop = Math.ceil(users / 1000); let limit = 0, offset = 0; for (let j = 0; j < loop; j++) { if (users > 1000) { limit = 1000; users -= limit; } else { limit = users; } console.log(limit + " limit " + offset + " offset"); var start = Date.now(); while (Date.now() < start + 100) {} const request = mailjet .get("messagesentstatistics") .request({ "CampaignID": id, "AllMessages": true, "Limit": limit, "Offset": offset }) request .then((result) => { let data = result.body.Data; var loop = 0; async.eachOfSeries(data, function1, function (err) { console.log("function"); callback2(); }) console.log("oooooo"); }) .catch((err) => { console.log(err); }) offset += limit; } function function1(value2, val, callback1) { console.log(data +" data"); let jsonObj = data[val]; let email = jsonObj.ToEmail; jsonObj['retailer'] = res[camp].retailer; jsonObj['summary'] = 'f'; let tempObj = {}; tempObj[id] = jsonObj; let options = { new: true }; let campId = id; User.addCampaignResponse(email, campId, tempObj, options, function (err, results) { if (err) { throw err; } else { console.log("aasd"); Campaign.updateResponse(_id, function (err, results2) { if (err) throw err; else { console.log("asdasaadas"); callback1(); } }) // console.log(results); } }) } } }, function (err) { callback(undefined, "doneeeeee"); }) Is there a better way than this? Can I use waterfall too somewhere? Can I change the callback positions to avoid the error?
EDIT: Simplified code
function function2(value1, i, callback2) { // ... const request = mailjet .get("messagesentstatistics") .request({ // ... }); request .then((result) => { // ... async.eachOfSeries(data, function1, function (err) { callback2(); }); }) .catch((err) => { // ... }); } function function1(value2, val, callback1) { // ... User.addCampaignResponse(email, campId, tempObj, options, function (err, results) { if (err) { throw err; } else { Campaign.updateResponse(_id, function (err, results2) { if (err) throw err; else callback1(); }); } }); } async.eachOfSeries(res, function (value, camp, callback3) { // ... async.eachOfSeries(arr, function2, function (err) { callback3(); }); }, function (err) { callback(undefined, "doneeeeee"); });
var start = Date.now(); while (Date.now() < start + 100) {}-- okay, I just have to ask. Why?