繁体   English   中英

For循环内的NodeJS和Mongoose回调

[英]NodeJS and Mongoose Callback inside a For Loop

这就是问题所在。 我有一个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); } }); }; 

因此,所有这些都可以与一个新的预订一起使用。 但是,现在我希望能够处理递归预订(每周进行预订)。 我已经重新创建了“创建”函数,并在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"); } } } 

好像是一个基本的异步调用问题,for循环不必等待回调被调用。

您可以使用异步 “系列”函数代替例如for循环。 这样,每个查找将在前一个查找之后被调用。

猫鼬还具有基于诺言的语法,可以帮助您: http : //mongoosejs.com/docs/promises.html

您可以使用异步eachSeries

async.eachSeries(users, function iterator(user, callback) {

    if(something) {
        //thing you want to do
        callback();
    } else {

        callback();
    }
}

由于您正在使用回调函数,因此有两种方法可以尝试解决此问题:1)使用一些外部库,该库允许您执行异步映射操作并针对每个冲突运行所有检查。 一旦完成,请检查合并结果是否冲突,并进行相应的处理,我建议使用异步库

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

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

除了声明使用let代替var之外,无需更改代码中的任何内容,并且循环应该起作用。

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

`
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无法用于在循环内运行异步代码的原因。 了解有关let的信息: https : //developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/let

在尝试了所有答案之后,我找到了解决方案。

我要做的是:

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的回复时都会调用该数组。

这样,我可以轻松比较预订数组的长度和ValidatorArray的长度。 当它们相等时,这意味着它已经从mongo收到了所有内容,并可以将响应发送回去。

谢谢您的帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM