关于Nodejs async parallel的问题
关于Nodejs async parallel的问题
现在我有一个数组,包含一组id, 然后用mongoose去查询更新数据
var ids = [1,2,3,4,5];
var successLen = 0;
ids.forEach(function(id) {
merchandiseModel.findByIdAndUpdate(id, {
$inc: {
order_num: 2
}
},
function(err, numberAffected, rawResponse) {
if(err){
console.error(err.message);
return;
}
if(numberAffected == 1)
successLen++;
});
}
用async如何去获取最后更新的成功数successLen?
现在我有一个数组,包含一组id, 然后用mongoose去查询更新数据 var ids = [1,2,3,4,5]; var successLen = 0; ids.forEach(function(id) { merchandiseModel.findByIdAndUpdate(id, { $inc: { order_num: 2 } }, function(err, numberAffected, rawResponse) {
if(err){
console.error(err.message);
return;
}
if(numberAffected == 1)
successLen++;
});
} 用async如何去获取最后更新的成功数successLen?
async.inject(ids, 0, function (successLen, id, callback) {
Model.findByIdAndUpdate(id, update, function (err, Model) {
if (err) return callback(err)
callback(null, ++successLen)
})
},
function (err, successLen) {
if (err) return // handle err...
console.log('successLen', successLen)
})
這樣寫會不會更簡單些:
Model.update(conditions, update, { multi: true }, function (err, numberAffected) {
if (err) return // handle err...
console.log('numberAffected', numberAffected)
})
參考討論看看。 :)
多谢,不过,你上面的有点问题,如果if(err)满足条件 callback(err),这样会导致立马执行最后一个函数,接下来的id不会再执行了. Model.update的话,如果是一个很大的数组,然后update的值是各不相同的,这个怎么写?比如数据: data = [{id: 1, num: 123}, {id:2, num: 321}…] 现在根据data数组的id去查找数据,找到后更新num,如何根据data写conditions,update?
如果不要 break loop 那就是用 async.each
了:
var successLen = 0
async.each(ids, function (id, callback) {
Model.findByIdAndUpdate(id, update, function (err, numberAffected) {
if (err) return callback(err)
if (numberAffected === 1) successLen++
callback(null)
})
},
function (err) {
if (err) return // handle err
console.log(‘successLen’, successLen)
})
丟一個 successLen
在外部我覺得這樣寫好醜,不曉得有沒有更漂亮的寫法。
Model.update
依不同 id 寫入不同 data 應該沒有辦法用一條簡單的條件句,可能一定得要用 loop 完成。
async好像只要调用callback(err)就会立刻中断, 最后我还是用你的async.inject处理的,不调用callback(err)就好 if(err) callback(null, successLen)
async.each
碰到 callback(err)
不會中斷吧?
async.each
最後的 callback 有兩種情況會被觸發:
- 當錯誤發生時,也就是
callback(err)
有傳入值進去 - 所有 iterator 完成時
值得注意的是,當發生 err 時第二個情況不會執行。示意:
async.each([1, 2, 3], function (item, done) {
console.log('item', item)
if (item === 2) return done(item)
done(null)
},
function (err) {
if (err) return console.log(‘err’, err)
console.log(‘done’)
})
// item 1
// item 2
// err 2
// item 3
async.each([1, 2, 3], function (item, done) {
console.log(‘item’, item)
done(null)
},
function (err) {
if (err) return console.log(‘err’, err)
console.log(‘done’)
})
// item 1
// item 2
// item 3
// done
[@chinghanho](/user/chinghanho) each果然会都执行一遍,我看到文档里的 >the main callback (for the each function) is immediately called with the error. 以为执行了main callback就表示结束了…,不过要统计成功的数目,还是用inject优雅点
在使用 Node.js 和 Mongoose 进行批量更新时,async
库中的 parallel
方法可以帮助你并行执行多个异步操作。这不仅可以提高效率,还能更清晰地组织代码。下面是如何使用 async.parallel
来处理你的需求,并获取最终成功更新的数量。
示例代码
首先,确保你已经安装了 async
库:
npm install async
然后,你可以按照以下方式重构你的代码:
const async = require('async');
const mongoose = require('mongoose');
// 假设 merchandiseModel 是你的 Mongoose 模型
const merchandiseModel = mongoose.model('Merchandise', new mongoose.Schema({}));
var ids = [1, 2, 3, 4, 5];
var successCount = 0;
async.parallel(
ids.map(id => callback =>
merchandiseModel.findByIdAndUpdate(id,
{ $inc: { order_num: 2 } },
{ new: true }, // 确保返回更新后的文档
(err, doc) => {
if (err) {
console.error(err.message);
callback(err); // 将错误传递给 async
return;
}
if (doc) {
successCount++;
}
callback(null, doc); // 成功时调用 callback 并传入结果
}
)
),
(err, results) => {
if (err) {
console.error("An error occurred:", err);
return;
}
console.log(`Total successful updates: ${successCount}`);
// results 包含每个异步操作的结果
}
);
解释
-
async.parallel
: 该函数接受两个参数:一个任务数组和一个回调函数。任务数组中的每个元素都是一个函数,该函数接收一个callback
函数作为参数。 -
ids.map
: 使用map
方法遍历ids
数组,并为每个id
创建一个任务。每个任务是一个函数,它调用findByIdAndUpdate
方法来更新数据库。 -
findByIdAndUpdate
: 这个方法用于查找文档并更新它。我们传递{ new: true }
参数以确保返回更新后的文档,而不是原始文档。 -
callback
: 在findByIdAndUpdate
的回调中,我们检查是否有错误发生。如果有错误,则通过callback(err)
传递错误。如果更新成功,我们增加successCount
计数器。 -
最终的回调: 当所有并行任务完成后,
async.parallel
的第二个参数将被调用。此时,results
参数包含了每个任务的结果。你可以在这里处理这些结果或进行其他清理工作。
这种方法不仅使代码更简洁、更易读,而且利用了 async.parallel
的能力来高效地并行执行多个异步操作。
在使用 async
库中的 parallel
方法来处理多个异步操作时,可以将每个更新操作放入一个函数中,然后使用 async.parallel
来并行执行这些函数。最终,通过回调函数来获取所有更新操作的结果,并计算成功更新的数量。
以下是一个示例代码:
const async = require('async');
const mongoose = require('mongoose');
// 假设 merchandiseModel 已经定义好
const merchandiseModel = mongoose.model('Merchandise', new mongoose.Schema({}));
var ids = [1, 2, 3, 4, 5];
var successLen = 0;
var tasks = ids.map(id => {
return function(callback) {
merchandiseModel.findByIdAndUpdate(id, {
$inc: {
order_num: 2
}
}, function(err, numberAffected) {
if (err) {
console.error(err.message);
return callback(err);
}
callback(null, numberAffected === 1);
});
};
});
async.parallel(tasks, function(err, results) {
if (err) {
console.error(err.message);
return;
}
successLen = results.filter(Boolean).length;
console.log(`Success updates: ${successLen}`);
});
解释
-
定义任务数组:
- 使用
ids.map
创建一个任务数组,其中每个任务是一个函数,该函数使用findByIdAndUpdate
更新文档,并在回调中传递结果。
- 使用
-
执行并行任务:
- 使用
async.parallel
并行执行所有任务。
- 使用
-
处理结果:
- 在
async.parallel
的回调函数中,results
是一个布尔值数组,表示每个更新是否成功。 - 使用
results.filter(Boolean).length
计算成功更新的数量。
- 在
这样就可以并行地执行多个更新操作,并统计成功更新的数量。