所以这就是问题所在。我有一个处理预订创建的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);
}
});
};
所以,所有这一切都适用于一个新的预订。但是,现在我希望能够处理递归预订(每周预订)。我重新创建了“创建”功能,并在validateBooking.bookingClash
内调用for loop
函数。
不幸的是,当我运行它时,它会完美地调用bookingClash函数,但是当它到达在数据库中进行搜索的行时:
Model.find({courtId: courtId, date: booking.date}, function(err, bookings)
它不等待回调,在处理响应“clash”之前,使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");
}
}
}
答案 0 :(得分:1)
看起来像一个基本的异步调用问题,for循环不等待回调被调用。
您可以使用async&#39;系列&#39; exmaple而不是for循环的函数。这样每个发现都会在前一个发现之后被调用。
Mongoose还有基于承诺的语法,可以帮助您:http://mongoosejs.com/docs/promises.html
答案 1 :(得分:1)
您可以使用async eachSeries
SUMX
答案 2 :(得分:1)
由于您使用的是回调函数,因此有两种方法可以尝试解决此问题: 1)使用一些外部库,允许您执行异步映射操作并对每个冲突运行所有检查。完成后,检查合并后的结果,然后进行相应的处理 我建议使用async library
您的代码看起来像:
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
答案 3 :(得分:1)
无需更改代码中的任何内容,除非声明使用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/en-US/docs/Web/JavaScript/Reference/Statements/let
答案 4 :(得分:0)
我在找到所有答案后找到了完成这项工作的方法。
我必须做的是:
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收到了所有东西,并且可以发回回复。
感谢您的帮助!