Javascript for循环中的async.fallower将转义for循环
在POST类型的表单操作中,我们获取Node.JS/Express中的所有值,并尝试将其保存到MongoDB中 隐藏字段根据前端javascript确定属性的长度,其值将更新为隐藏字段的值 此长度在后端节点中用于迭代项目列表 我有一个async.瀑布函数和一个for循环,在其中运行,如下所示Javascript for循环中的async.fallower将转义for循环,javascript,node.js,mongodb,asynchronous,mongoose,Javascript,Node.js,Mongodb,Asynchronous,Mongoose,在POST类型的表单操作中,我们获取Node.JS/Express中的所有值,并尝试将其保存到MongoDB中 隐藏字段根据前端javascript确定属性的长度,其值将更新为隐藏字段的值 此长度在后端节点中用于迭代项目列表 我有一个async.瀑布函数和一个for循环,在其中运行,如下所示 async.waterfall([ function(callback){ var itemLength = req.body.itemLength; var itemProp
async.waterfall([
function(callback){
var itemLength = req.body.itemLength;
var itemProp,itemComponent;
var destination;
var destinationsArray =[];
for(var k=1; k<=itemLength; k++){
destination = new Destination({
name: req.body['destinationName'+k],
});
itemComponent = {
"itemCompProp" : req.body['itemCompProp'+k]
};
itemProp = new ItemProp({
itemComponent: itemComponent
});
itemProp.save(function(err,itemPropSaved){
destination.newProperty = itemPropSaved._id
destination.save(function(err,destinationSaved){
if(err){
console.log("Error== " + err);
}
else{
destinationsArray.push(destinationSaved._id);
}
});
});
}// End of For
callback(null,destinationsArray);
},
function(destinationsArray,callback){
var brand = new Brand({
name : req.body.brandName,
});
brand.save(function(err,brandSaved){
if(err){
console.log("Error== " + err);
}else{
console.log('Brand Saved');
}
});
callback(null);
}
], function (err, status) {
if(err){
req.flash('error', {
msg: 'Error Saving Brands'
});
console.log("Error : " + err);
}
else{
console.log("Brand Saved.");
req.flash('success', {
msg: 'Brand Successfully Added!'
});
}
});
res.redirect('/redirectSomewhere');
当我们运行此操作时,destinationsArray首先返回为null,而不是通过for循环,然后返回destinationsArray在目标的长度itemLength上的正确值
我们希望这个过程是同步的。我们还尝试使用一个封装for循环的闭包,但没有效果
我们不能使用async.eachSeries而不是for循环,因为我只是在迭代一个数值属性,我们没有任何文档可以迭代
在async.瀑布中运行for循环是否有可行的解决方案
干杯并提前感谢。问题与callbacknull、destinationsArray有关;在for循环外部调用,而不首先检查循环是否已完成
尝试替换callbacknull、destinationsArray;比如说:
if (itemLength > 0 && destinationsArray.length === k - 1) {
callback(null, destinationsArray);
} else {
callback(true);
}
以上检查确保destination.save成功完成正确次数
实际上我更喜欢djskinner提出的方法。但是,由于存在保存错误时会出现console.log,callbacked destinationsArray可能包含不正确的项数。要解决这个问题,您可以确保更换控制台;使用callbackerr之类的工具来结束瀑布,并返回错误。此外,k===itemLength检查不能正确说明应该保存的项目的正确数量。这应该替换为k==destinationsArray.length
我做了一些修改来修复这个问题,并在下面发布了一个更新版本
destination.save(function(err, destinationSaved){
if (err) {
callback(err);
}
else {
destinationsArray.push(destinationSaved._id);
if (k === destinationsArray.length) {
callback(null, destinationsArray);
}
}
});
-编辑-我真的很喜欢Ben发布的解决方案。这允许在迭代连续运行的地方创建循环。有关更多信息,请查看npm页面。该问题与callbacknull、destinationsArray有关;在for循环外部调用,而不首先检查循环是否已完成
尝试替换callbacknull、destinationsArray;比如说:
if (itemLength > 0 && destinationsArray.length === k - 1) {
callback(null, destinationsArray);
} else {
callback(true);
}
以上检查确保destination.save成功完成正确次数
实际上我更喜欢djskinner提出的方法。但是,由于存在保存错误时会出现console.log,callbacked destinationsArray可能包含不正确的项数。要解决这个问题,您可以确保更换控制台;使用callbackerr之类的工具来结束瀑布,并返回错误。此外,k===itemLength检查不能正确说明应该保存的项目的正确数量。这应该替换为k==destinationsArray.length
我做了一些修改来修复这个问题,并在下面发布了一个更新版本
destination.save(function(err, destinationSaved){
if (err) {
callback(err);
}
else {
destinationsArray.push(destinationSaved._id);
if (k === destinationsArray.length) {
callback(null, destinationsArray);
}
}
});
-编辑-我真的很喜欢Ben发布的解决方案。这允许在迭代连续运行的地方创建循环。有关更多信息,请查看npm页面。与其说是For循环导致了问题,不如说是save是一个异步操作。for循环完成,并且在任何save回调有机会完成之前执行回调 您要做的是在执行了所有目标save回调之后调用async.fallower回调。比如:
destination.save(function(err,destinationSaved){
if(err){
console.log("Error== " + err);
} else {
destinationsArray.push(destinationSaved._id);
if (k === itemLength) {
// all destination callbacks have completed successfully
callback(null, destinationsArray);
}
}
});
造成问题的与其说是for循环,不如说是save是一个异步操作。for循环完成,并且在任何save回调有机会完成之前执行回调 您要做的是在执行了所有目标save回调之后调用async.fallower回调。比如:
destination.save(function(err,destinationSaved){
if(err){
console.log("Error== " + err);
} else {
destinationsArray.push(destinationSaved._id);
if (k === itemLength) {
// all destination callbacks have completed successfully
callback(null, destinationsArray);
}
}
});
这里的代码几乎没有问题: 回拨电话的地方。 res.redirect接到电话的地方。 for循环。 保存是异步的。常规for循环将继续,而不等待所有save调用完成。这就是destinationsArray为空的原因。正如您所说的,您不能使用async.eachSeries,因为您正在迭代数值属性。然而,你在这方面走的是对的。Async.while就是这样做的。下面是修改后的代码,其中包含Async.while和回调的正确调用位置:
async.waterfall([
function(callback){
var itemLength = req.body.itemLength;
var itemProp,itemComponent;
var destination;
var destinationsArray =[];
var k = 1; // 1st part of for loop: for(k=1; k<=itemLength; k++)
async.whilst(
function() {
return k <= itemLength; // 2nd part of for loop: for(k=1; k<=itemLength; k++)
},
function(whilstCb) {
destination = new Destination({
name: req.body['destinationName'+k]
});
itemComponent = {
"itemCompProp" : req.body['itemCompProp'+k]
};
itemProp = new ItemProp({
itemComponent: itemComponent
});
itemProp.save(function(err,itemPropSaved){
destination.newProperty = itemPropSaved._id
destination.save(function(err,destinationSaved){
if(err){
console.log("Error== " + err);
} else {
destinationsArray.push(destinationSaved._id);
}
k++; // 3rd part of for loop: for(k=1; k<=itemLength; k++)
whilstCb(null);
});
});
},
function(err) {
// It gets here once the loop is done
console.log(destinationsArray); // This array should have all the values pushed
callback(null, destinationsArray);
}
);
},
function(destinationsArray,callback){
var brand = new Brand({
name : req.body.brandName
});
brand.save(function(err,brandSaved){
if(err){
console.log("Error== " + err);
} else {
console.log('Brand Saved');
}
callback(null);
});
}
], function (err, status) {
if(err){
req.flash('error', {
msg: 'Error Saving Brands'
});
console.log("Error : " + err);
} else {
console.log("Brand Saved.");
req.flash('success', {
msg: 'Brand Successfully Added!'
});
}
res.redirect('/redirectSomewhere');
});
这里的代码几乎没有问题: 回拨电话的地方。 res.redirect接到电话的地方。 for循环。 保存是异步的。常规for循环将继续,而不等待所有save调用完成。这就是destinationsArray为空的原因。正如您所说的,您不能使用async.eachSeri 因为您正在迭代数值属性,所以会出现错误。然而,你在这方面走的是对的。Async.while就是这样做的。下面是修改后的代码,其中包含Async.while和回调的正确调用位置:
async.waterfall([
function(callback){
var itemLength = req.body.itemLength;
var itemProp,itemComponent;
var destination;
var destinationsArray =[];
var k = 1; // 1st part of for loop: for(k=1; k<=itemLength; k++)
async.whilst(
function() {
return k <= itemLength; // 2nd part of for loop: for(k=1; k<=itemLength; k++)
},
function(whilstCb) {
destination = new Destination({
name: req.body['destinationName'+k]
});
itemComponent = {
"itemCompProp" : req.body['itemCompProp'+k]
};
itemProp = new ItemProp({
itemComponent: itemComponent
});
itemProp.save(function(err,itemPropSaved){
destination.newProperty = itemPropSaved._id
destination.save(function(err,destinationSaved){
if(err){
console.log("Error== " + err);
} else {
destinationsArray.push(destinationSaved._id);
}
k++; // 3rd part of for loop: for(k=1; k<=itemLength; k++)
whilstCb(null);
});
});
},
function(err) {
// It gets here once the loop is done
console.log(destinationsArray); // This array should have all the values pushed
callback(null, destinationsArray);
}
);
},
function(destinationsArray,callback){
var brand = new Brand({
name : req.body.brandName
});
brand.save(function(err,brandSaved){
if(err){
console.log("Error== " + err);
} else {
console.log('Brand Saved');
}
callback(null);
});
}
], function (err, status) {
if(err){
req.flash('error', {
msg: 'Error Saving Brands'
});
console.log("Error : " + err);
} else {
console.log("Brand Saved.");
req.flash('success', {
msg: 'Brand Successfully Added!'
});
}
res.redirect('/redirectSomewhere');
});
工作起来很有魅力。完美的非常感谢!不知道async.while.Works很有魅力。完美的非常感谢!不知道async.while。