NodeJS POST保持挂起状态

时间:2014-03-03 09:10:34

标签: node.js post callback mongoose callstack

我发布了一个带有jQuery的json字符串到我的NodeJS后端,并且遇到了后端发布数据的问题。看起来后端在某处阻塞,但我无法找到它。因此,我的POSTS保持状态挂起,有时它返回OK 200。

我的代码循环使用async.forEach retValTravelInsurerList,它是一个由23家保险公司组成的数组。我有一个嵌套的async.forEach,它使用值设置构造函数,并在filterTravelInsurerCoverage中执行查询。这意味着通过Mongoose(MongoDB)数据库执行23个查询。

如果在过滤器TerminalInsurerCoverage数组中找到它们,我只需要retValTravelInsurerList中的项目,我将填充一个新数组(retValTravelInsurerAndCoverageList),其中存储了所有需要的项目。

如果travelinsurercoverage具有retValTravelInsurerList =>中所有项目的覆盖范围,则POST状态没有问题。让我们说23。

但是如果生成的数组(retValTravelInsurerAndCoverageList)长度小于(travelinsurercoverage)长度,则会发生POST问题,如果我向服务器发布了几次,则状态会在Chrome的javascript控制台中保持“PENDING”。

在我看来,NodeJS调用堆栈中仍有一些项目阻塞了未来的POSTS,即使在返回callback()时也是如此;被称为。

有人知道如何解决这个问题吗?

顺便说一句:我使用异步库,并在返回callback()之后;被称为res.send(JSON.stringify(retValTravelInsurerAndCoverageList));被称为。

function(callback) {
  var count = 0;
  async.forEach(retValTravelInsurerList, function(item, callback1) {

    count++;

    travelinsurercoverageMdl.constructorTravelInsurerCoverage('', item._id, item.familytype,'','',this.wintersport,'',this.adventuresport, this.accidents,'','','','',this.motoristaid,'','','');
    travelinsurercoverageMdl.filterTravelInsurerCoverage(function(travelinsurercoverage, callback2){

      count--;

      async.forEach(travelinsurercoverage, function(item2, callback3) {

        retValTravelInsurerAndCoverageList.push({

          //I have shorted the list below, to 
          //get a better overview of the code
          //travel_insurer
          _id: item._id,
          name: item.name

          //travel_insurercoverage                        
          adventuresport: item2.adventuresport,
          accidents: item2.accidents,
          cashcoverageextraamount: item2.cashcoverageextraamount

          //extra fields
          familytype: item.familytype
        });

        if(count == 0) {
          return callback(); //if count is subtracted completely, then the list is finished and can be calledback to the res.send function.
        }
      }, callback1); //callback to retValTravelInsurerList to get the next item in the array.
    });
  });
}],
function(err) {
  if(err){
    return (err);
  } else {
    res.send(JSON.stringify(retValTravelInsurerAndCoverageList));
  }
});

下面是函数filterTravelInsurerCoverage声明,它由内部async.forEach调用。动态where和数组被缩短......

   async.series([

    function(callback)
    {
        //define the model
        var travelinsurercoverageModel = conn.model('travel_insurercoverages', schema);

        //define the query
        var query = travelinsurercoverageModel.find();

        //build dynamic where
        if(utilnull.isItemNullValue(locals._cancellation3000))
        { query.where({'Cancellation3000': {'$gte' : 0}}); }
        if(utilnull.isItemNullValue(locals._motoristaid))
        { query.where({'MotoristAid': {'$gte' : 0}}); }
        if(utilnull.isItemNullValue(locals._businesstravel))
        { query.where({'BusinessTravel': {'$gte' : 0}}); }
        if(utilnull.isItemNullValue(locals._extendedtravelperiod))
        { query.where({'ExtendedTravelPeriod': {'$gte' : 0}}); }
        if(utilnull.isItemNullValue(locals._extendedtravelprice))
        { query.where({'ExtendedTravelPrice': {'$gte' : 0}}); }

        //execute query
        query.exec(function (err, reis) {
            if (err) return callback(err);

            reis.forEach(function(item) {

                retVal.push({
                    _id: item.id,
                    insuranceidref: item.InsuranceIDREF,
                    familytype: item.FamilyType,
                    basepriceeurope: item.BasePriceEurope,
                    businesstravel: item.BusinessTravel,
                    extendedtravelperiod: item.ExtendedTravelPeriod,
                    extendedtravelprice: item.ExtendedTravelPrice
                });
            });
            callback();
        })
    }
    ],
    function(err)
    {
        if(err){
            return err;
        }
        else {
            callback(retVal);
        }
    }
    );

1 个答案:

答案 0 :(得分:1)

问题似乎与您的回调处理有关。

async.forEach的使用方式如下:

async.forEach(array, function(item, next) {
  // do stuff with item, which comes from the array
  next();
  // ALWAYS invoke next(). If you have an error and need to stop the processing, pass an error argument
}, function(err) {
  // end callback, invoked when all item where processed, of when an error is reported
});

forEach将并行处理您的资料。如果您需要停止它们,请错误地调用next,并且将调用您的结束回调,而不会触发其他未处理的项目。

您永远不应该使用return,抛出错误或从父作用域调用另一个回调来破坏此工作流。

---编辑 -

例如,你可以这样:

function(callback) {

  async.forEach(retValTravelInsurerList, function(item, next1) {

    travelinsurercoverageMdl.constructorTravelInsurerCoverage('', item._id, item.familytype,'','',this.wintersport,'',this.adventuresport, this.accidents,'','','','',this.motoristaid,'','','');

    // here is an asynchronous processing: next1 will be invoked when it ends
    travelinsurercoverageMdl.filterTravelInsurerCoverage(function(travelinsurercoverage, callback2){

    async.forEach(travelinsurercoverage, function(item2, next2) {

      retValTravelInsurerAndCoverageList.push({

        //I have shorted the list below, to 
        //get a better overview of the code
        //travel_insurer
        _id: item._id,
        name: item.name

        //travel_insurercoverage                        
        adventuresport: item2.adventuresport,
        accidents: item2.accidents,
        cashcoverageextraamount: item2.cashcoverageextraamount

        //extra fields
        familytype: item.familytype
      });
      // item2 processing is finished: let nested async.forEach knows about it
      next2();
    }, next1); // when all item2 in travelinsurercoverage are processed, let first async.forEach knows about it
  }, callback); // when all item in retValTravelInsurerList are processed, your overall processing is ok.