【问题标题】:Request in NodeJS async waterfall return undefinedNodeJS异步瀑布中的请求返回未定义
【发布时间】:2018-03-22 21:45:28
【问题描述】:

我对节点 js 上的异步还很陌生。我在解析这样的 xml 文件时使用瀑布方法:

$('situation').each( function(){
var situation = [];
$(this).find('situationRecord').each( function(i){
  var record = this;
  async.waterfall([
    function (callback){
      var filter = {
        startLocationCode: $(record).find('alertCMethod2SecondaryPointLocation').find('specificLocation').text(), 
        endLocationCode: $(record).find('alertCMethod2PrimaryPointLocation').find('specificLocation').text(),
        overallStartTime: $(record).find('overallStartTime').text(),
        overallEndTime: $(record).find('overallEndTime').text()
      }
      callback(null, filter, record);
    },
    function (filter, record, callback){
      var timestamp = new Date().toDateInputValue();
      var startDbResponse = 0;
      var endDbResponse = 0;
      if((filter.startLocationCode != '') && new Date(timestamp) >= new Date(filter.overallStartTime) && new Date(timestamp) <= new Date(filter.overallEndTime) ){
        startDbResponse = locationCodeToGeodataRequst.geodataByLocationcode(filter.startLocationCode);
        endDbResponse = locationCodeToGeodataRequst.geodataByLocationcode(filter.endLocationCode);
      }
      console.log("startDbResponse: ", startDbResponse);
      console.log("endDbResponse: ", endDbResponse);
      callback(null, filter, record, startDbResponse, endDbResponse);
    },
    function (filter, record, startDbResponse, endDbResponse, callback){
     console.log("startDbResponse: ", startDbResponse);
     console.log("endDbResponse: ", endDbResponse);          
     var situationRecord = createSituationRecord($, record, filter.startLocationCode, filter.endLocationCode, startDbResponse, endDbResponse);
      console.log(situationRecord);
    },
    function (situationRecord, callback){
      situation[i] = { situationRecord };
    }
  ],
  function(err, results){
    console.error("There was an error by filtering the xml file");
    console.error(err);
  });
})
if(situation.length > 0){ //if situation is not empty
  locations.push(situation);
}
})
 console.log(locations);
}

在瀑布的这一部分,我使用locationCodeToGeodataRequst.geodataByLocationcode(filter.startLocationCode); 向我的数据库发出请求,但startDbResponseendDbResponseundefined

 ....
 function (filter, record, callback){
      var timestamp = new Date().toDateInputValue();
      var startDbResponse = 0;
      var endDbResponse = 0;
      if((filter.startLocationCode != '') && new Date(timestamp) >= new Date(filter.overallStartTime) && new Date(timestamp) <= new Date(filter.overallEndTime) ){

        startDbResponse = locationCodeToGeodataRequst.geodataByLocationcode(filter.startLocationCode);
        endDbResponse = locationCodeToGeodataRequst.geodataByLocationcode(filter.endLocationCode);

      }
      console.log("startDbResponse: ", startDbResponse);
      console.log("endDbResponse: ", endDbResponse);
      callback(null, filter, record, startDbResponse, endDbResponse);
    },
....

它自己的请求可以工作,因为请求模块中的 console.log 显示了正确的数据。所以我不明白为什么它是未定义的。

这是请求模块:

exports.geodataByLocationcode = function geodataByLocationcode(locationcode){
 let sql = "SELECT * FROM tmc WHERE LOCATION_CODE = " + locationcode;
 let query = db.query(sql, (err, result) =>{
  if(err == null){
    //console.log(result);
    return result;
  }else{
    console.log("Error by getting item from db: " + err);
    throw err;
  }
 });
}

这是 console.log 的片段:

....
startDbResponse:  undefined
endDbResponse:  undefined
startDbResponse:  undefined
endDbResponse:  undefined
startDbResponse:  0
endDbResponse:  0
startDbResponse:  0
endDbResponse:  0
[]
//here comes the output of the requests as json objects
.... 

【问题讨论】:

  • 因为 locationCodeToGeodataRequst.geodataByLocationcode(filter.startLocationCode) 这个 api 需要时间来执行,并且您可以更早地进行控制台打印
  • 但是在下面的函数中这两个变量仍然是未定义的
  • 能提供合适的功能吗?我只能看到两个控制台在运行,所以控制台如何打印 4 次
  • 我刚刚添加了两个console.logs。这与我在本地机器上使用的代码相同,我只是删除了一些不重要的 console.logs

标签: javascript node.js request async.js waterfall


【解决方案1】:

将控制台日志移动到 async 的最后一个函数。正如 Manjeet 指出的那样,异步需要时间,并且控制台会提前打印。

  function (situationRecord, callback){
  situation[i] = { situationRecord };
  if(situation.length > 0){ //if situation is not empty
    locations.push(situation);
  }
  })
   console.log(locations);
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-28
    • 2020-06-14
    • 2014-10-09
    • 1970-01-01
    • 2017-04-26
    • 2018-08-14
    • 2019-08-24
    • 2020-01-31
    相关资源
    最近更新 更多