【问题标题】:NodeJS and Mongoose Callback inside a For LoopFor 循环内的 NodeJS 和 Mongoose 回调
【发布时间】:2018-04-07 23:34:33
【问题描述】:

所以这就是问题所在。我有一个处理预订创建的 REST API,但是,在将预订保存到 mongo 之前,它会验证是否与另一个预订发生冲突。

exports.create = function(req, res) {
    var new_type = new Model(req.body);
    var newBooking = new_type._doc;

    //check if the new booking clashes with existing bookings
    validateBooking.bookingClash(newBooking, function(clash){
        if(clash == null) // no clashes, therefore save new booking
        {
            new_type.save(function(err, type) {
                if (err)
                {
                    res.send(err); //error saving
                }
                else{
                    res.json(type); //return saved new booking
                }
            });
        }
        else //clash with booking
        {
            //respond with "clashDate"
        }
    });
};

这里有验证功能,可以检查当天是否与预订发生冲突:

exports.bookingClash = function (booking, clash) {
    //find the bookings for the same court on the same day
    var courtId = (booking.courtId).toString();

    Model.find({courtId: courtId, date: booking.date}, function(err, bookings) {
        if(err == null && bookings == null)
        {
            //no bookings found so no clashes
            clash(null);
        }
        else //bookings found
        { 
            //for each booking found, check if the booking start hour falls between other booking hours
            for(var i = 0; i<bookings.length ; i++)
            {
                //here is where I check if the new booking clashes with bookings that are already in the DB 
                {
                    //the new booking clashes
                    //return booking date of the clash
                    clash(clashDate); //return the clashDate in order to tell the front-end
                    return;
                }
            }
            //if no clashes with bookings, return null
            clash(null);
        }
    });
};

因此,所有这些都适用于一个新的预订。但是,现在我希望能够处理递归预订(每周进行的预订)。我重新创建了“create”函数并在for loop 中调用了validateBooking.bookingClash 函数。

不幸的是,当我运行它时,它完美地调用了 bookingClash 函数,但是当它到达在数据库中进行搜索的行时:

Model.find({courtId: courtId, date: booking.date}, function(err, bookings)

它不等待回调并且在处理响应“冲突”之前,使 i++ 并继续。

如何让它工作并等待回调?

var array = req.body;
var clashes = [];

for(var i = 0; i<array.length;i++)
     {
         validateBooking.bookingClash(array[i], function(clash)
         {
           if(clash)
           {
               clashes.push(clash);
           }
           else{
              console.log("no clash");
           }
         }
     }

【问题讨论】:

    标签: javascript node.js mongodb mongoose callback


    【解决方案1】:

    看起来像一个基本的异步调用问题,for循环不等待回调被调用。

    您可以使用 async 'series' 函数作为示例,而不是 for 循环。这样每个 find 都会在前一个 find 之后被调用。

    Mongoose 还有一个基于 Promise 的语法可以帮助你:http://mongoosejs.com/docs/promises.html

    【讨论】:

      【解决方案2】:

      您可以使用async eachSeries

      async.eachSeries(users, function iterator(user, callback) {
      
          if(something) {
              //thing you want to do
              callback();
          } else {
      
              callback();
          }
      }
      

      【讨论】:

        【解决方案3】:

        由于您使用的是回调函数,因此您可以尝试两种方法来解决此问题: 1)使用一些外部库,允许您执行异步映射操作并为每次冲突运行所有检查。完成后,检查组合结果是否存在冲突并相应地进行 我建议使用async library

        您的代码将类似于: async.map(array,(entry,callback) =&gt; validateBooking.bookingClash(entry,callback),(error,mappingResults)=&gt;{...})

        2) 您可以尝试将此函数更改为递归函数

        `function recursiveValidation(arrayToCheck,mainCallback){ 
        if(arrayToCheck.length === 0) {
           return cb(null} // end of array without errors
        } 
        
        validateBooking.bookingClash(_.head(arrayToCheck), function(clash)
             {
               if(clash)
               {
                   return mainCallback(clash);
               }
        
                return  recursiveValidation(_.tail(arrayToCheck),mainCallback);
        
             }
        }`
        

        上面的代码只是一个模型,但它应该说明这一点。 _ 是lodash

        【讨论】:

          【解决方案4】:

          除了声明使用 let 而不是 var 之外,无需更改代码中的任何内容,并且您的循环应该可以工作。

          var 数组 = req.body; var 冲突 = [];

          `
          for(**let** i = 0; i<array.length;i++)
               {
                   validateBooking.bookingClash(array[i], function(clash)
                   {
                     if(clash)
                     {
                         clashes.push(clash);
                     }
                     else{
                        console.log("no clash");
                     }
                   }
               }`
          

          您必须了解 let 和 var 之间的区别。还有为什么 var 不能用于在循环内运行异步代码。 了解让:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

          【讨论】:

            【解决方案5】:

            在尝试了你所有的答案后,我找到了完成这项工作的方法。

            我必须做的是:

            validateBooking.singleBooking(new_type._doc, newBookingClubId, function (clash) {
                            if (clash == null) // no clash
                            {
                                validatorArray.push(0);
                                if(validatorArray.length == array.length) //has received everything from mongo
                                {
                                    console.log("Clashes: " + clashes.toString());
                                    if(validatorArray.indexOf(1) > -1) //contains a clash
                                    {
                                        var error = {
                                            code: 409,
                                            message: "409 Conflict",
                                            clashes: clashes
                                        };
                                        errorsHandler.handleError(error, res);
                                    }
            

            这样,我创建了一个名为“validatorArray”的数组,每次我从 Mongo 收到返回的东西时都会调用它。

            这样我可以轻松地比较预订数组的长度和验证器数组的长度。当它们相等时,这意味着它已经收到了来自 mongo 的所有内容,并且可以发回响应。

            感谢您的帮助!

            【讨论】:

              猜你喜欢
              • 2021-05-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-09-17
              • 2017-06-02
              • 2020-04-17
              • 2017-05-03
              相关资源
              最近更新 更多