Node.js在for循环中调用calback函数

时间:2017-08-03 13:27:24

标签: javascript node.js callback

我试图在for循环中调用一个函数,问题是在循环结束后调用该函数。

以下面的例子为例,它打印到控制台:
here1
here1
here2
here2

而不是
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
        });
      });
    });
  });
});

我该如何解决这个问题?

如果我需要提供更多信息,请告诉我

以下是完整的代码:

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);
              }
            });
          }
        });
      });
    });
  }
}

这些是回调函数:

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);
  });
}

我的目标是在failureList数组完成循环后返回compliance数组

我发现了一个类似的问题here,但不确定这是否适合我的情况而且我真的不知道如何实施承诺

2 个答案:

答案 0 :(得分:-1)

for循环按顺序执行作用域内的语句。但它不等待函数调用完成,它继续下一个语句(即异步工作)。这就是为什么结果如此。您可以使用Promises或使用async模块同步工作。

由于目前尚不清楚您将在函数调用中执行什么以及您希望语句执行什么操作,因此我无法建议其中任何一个。 。 asyn.each通常是首选,以使for循环同步执行。当您想要等待函数完成执行然后执行操作时,将使用promise。您可能想查看他们的文档

Promises|MDN

async.each

谢谢你,Ragul

答案 1 :(得分:-1)

如果你想按顺序使用async.eachOfSeries

class ApplicationSpec extends PlaySpec with Results with GuiceOneAppPerTest with Injecting {
    "Application" should {
        "work" in {
          implicit lazy val materializer: Materializer = app.materializer
          val controller = new Application(inject[ControllerComponents])
          val body = Json.obj()
          val result = call(controller.work(), FakeRequest(POST, "/work").withHeaders((CONTENT_TYPE, "application/json")).withJsonBody(body))
          contentAsJson(result) mustBe body
        }
      }
    }

如果您想优化流程,请查看async.parallel