Node.js calls a callback function inside a for loop

I am trying to call a function inside a loop for, and the problem is that the function is called after the loop ends.

Taking the example below, it prints to the console:
here1
here1
here2
here2

Instead of here1
here2
here1
here2

report.forEach(item => {
  item.runs.forEach(run => {
    waComplianceBusiness(req, run.id, (err, res) => {
      const compliance = res.data.overviews[0].compliance;
      var failureList = [];

      compliance.forEach((rule, index) => {
        console.log('here1');
        waRuleOverview(req, run.id, rule.id, (err, res) => {
          console.log('here2');
          // handle the response
        });
      });
    });
  });
});

How can i fix this?

Please let me know if I need to provide more information.


Here is the complete code:

export default (req, callback) => {
  const report = req.body.webAudits;

  if(report.length > 0) {
    report.forEach(item => {
      item.runs.forEach(run => {
        waComplianceBusiness(req, run.id, (err, res) => {
          const compliance = res.data.overviews[0].compliance;
          if(compliance) {
            var failureList = [];
            compliance.forEach((rule, index) => {
              if(rule.pagesFailed > 0) {
                waRuleOverview(req, run.id, rule.id, (err, res) => {
                  const failedConditions = res.data.failedConditions;
                  const ruleName = res.data.ruleName;

                  failedConditions.forEach((condition, failedIndex) => {
                    const request = {
                      itemId: condition.conditionResult.id,
                      itemType: condition.conditionResult.idType,
                      parentId: condition.conditionResult.parentId,
                      parentType: condition.conditionResult.parentType
                    }
                    const body = {
                      runId: run.id,
                      ruleId: rule.id,
                      payload: request
                    }

                    waConditionOverview(req, body, (err, res) => {
                      const description = res.data.description;
                      const conditionValues = res.data.conditionValues[0];
                      var actualValue = conditionValues.value;

                      if(actualValue == "") {
                        actualValue = 'empty';
                      }

                      if(description.idType == "variable") {
                        var failureObj = {
                          ruleName: ruleName,
                          expected: description.name + ' ' + description.matcher + ' ' + description.expected[0],
                          actual: description.name + ' ' + description.matcher + ' ' + actualValue
                        };
                      }
                      else if(description.idType == "tag") {
                        var failureObj = {
                          ruleName: ruleName,
                          expected: description.name + '\n' + description.matcher,
                          actual: actualValue
                        };
                      }
                      failureList.push(failureObj);
                    });
                  });
                });
              }
              if(key + 1 == compliance.length) {
                console.log(failureList);
              }
            });
          }
        });
      });
    });
  }
}

These are the callback functions:

export function waComplianceBusiness(req, runId, callback) {
  const apiToken = req.currentUser.apiToken;
  const payload = {
    'Authorization': 'api_key ' + apiToken
  }

  const options = {
    'method': 'get',
    'gzip': true,
    'headers': payload,
    'content-type': 'application/json',
    'json': true,
    'url': 'api_url'
  }

  request(options, (error, response, body) => {
    callback(null, body);
  });
}

export function waRuleOverview(req, runId, ruleId, callback) {
  const apiToken = req.currentUser.apiToken;
  const payload = {
    'Authorization': 'api_key ' + apiToken
  }

  const options = {
    'method': 'get',
    'gzip': true,
    'headers': payload,
    'content-type': 'application/json',
    'json': true,
    'url': 'api_url'
  }

  request(options, (error, response, body) => {
    callback(null, body);
  });
}

export function waConditionOverview(req, body, callback) {
  const apiToken = req.currentUser.apiToken;
  const payload = {
    'Authorization': 'api_key ' + apiToken
  }

  const options = {
    'method': 'post',
    'gzip': true,
    'headers': payload,
    'body': body.payload,
    'content-type': 'application/json',
    'json': true,
    'url': 'api_url'
  }

  request(options, (error, response, body) => {
    callback(null, body);
  });
}

My goal is to return an array failureListafter loop over arraycompliance

I found a similar question here , but not sure if this will work in my case, and I really don't know how to implement promises

+6
source share
2

for . , (.. ). . Promises async.

, , ., asyn.each for. promises , , . ,

Promises | MDN

async.each

,

-1

, async.eachOfSeries

   async.eachOfSeries(report, function(item, index, eachOfCallback1){

       async.eachOfSeries(item.runs, function(run, index, eachOfCallback2){

          waComplianceBusiness(req, run.id, (err, res) => {

              var failureList = [];
              async.eachOfSeries(compliance, function(rule, index, eachOfCallback3){

                 console.log('here1');
                 waRuleOverview(req, run.id, rule.id, (err, res) => {
                     console.log('here2');
                     return eachOfCallback3(err);
                 });

               }, function(err){
                 if(err)
                    return eachOfCallback2(err);
                 else return eachOfCallback2();
               });

           });
        }, function(err){
           if(err)
              return eachOfCallback1(err);
           else return eachOfCallback1();
        })
    }, function(err){
       // handle final response  
    })

, async.parallel

-1

Source: https://habr.com/ru/post/1682945/


All Articles