JavaScript中MongoDB批量更新时无法同步打印控制台消息
问题
批量更新数据库记录时,更新状态消息延迟到全部操作完成后才批量打印,而非逐条按迭代顺序输出。其中console.log('filter & up===> ', filter, upObj, serchKeyVal);能正常逐条打印,但数据库更新的成功/错误消息全部延迟输出。
原代码
const updateRecord = async (records, connObj) => { try{ const isExistKey = records.some(obj => obj.hasOwnProperty(config.collectionKey)); let collKey = config.collectionKey; console.log('collection key=========> ', isExistKey); if(isExistKey) { let updateCount = 1; for(let obj of records) { if(obj[collKey] && obj[collKey] === '') { console.log(`The search key value is missing for row ${updateCount} from the sheet.`); }else{ let serchKeyVal = obj[collKey]; let filter = { [collKey]: obj[collKey] } delete obj[collKey]; let flag = Object.values(obj).every((v) => v !== ''); if(!flag) { console.log(`Some of the values are missing for row ${updateCount} from sheet. So could not update.`); }else{ const upObj = obj; console.log('filter & up===> ', filter, upObj, serchKeyVal); await connObj.collection(config.mongoCollection).updateOne(filter, { $set: upObj }, function (err, data) { if(err) { console.log(`Record could not updated with for ${serchKeyVal}`); console.log('Error while updating record====> ', err); }else{ if(data.result.nModified === 1) { console.log(`Record updated successfully for ${serchKeyVal}`); }else{ console.log(`No matched record/No new value to update for ${serchKeyVal}`); } } }); } } updateCount++; } }else{ console.log('The collection key is not found in csv sheet.'); } }catch(error) { console.log('Error while updating records ===> ', error); } }
问题原因
调用updateOne时传入了回调函数,此时MongoDB驱动会采用回调模式执行,不会返回Promise,导致await关键字无法等待异步操作完成。循环会直接快速遍历所有记录发起更新请求,而所有回调函数会在后续数据库操作完成后集中执行,因此状态消息会批量延迟输出。
解决方法
方法1:使用Promise版本的updateOne(推荐)
移除回调函数,直接await驱动返回的Promise,这样循环会等待当前更新操作完成后再进入下一次迭代,确保消息按顺序输出:
// 替换原updateOne调用部分 const upObj = obj; console.log('filter & up===> ', filter, upObj, serchKeyVal); try { const data = await connObj.collection(config.mongoCollection).updateOne(filter, { $set: upObj }); if(data.result.nModified === 1) { console.log(`Record updated successfully for ${serchKeyVal}`); } else { console.log(`No matched record/No new value to update for ${serchKeyVal}`); } } catch (err) { console.log(`Record could not updated with for ${serchKeyVal}`); console.log('Error while updating record====> ', err); }
方法2:将回调包装为Promise
如果需要保留回调逻辑,可以手动将其包装为Promise,让await能够等待操作完成:
// 替换原updateOne调用部分 const upObj = obj; console.log('filter & up===> ', filter, upObj, serchKeyVal); await new Promise((resolve, reject) => { connObj.collection(config.mongoCollection).updateOne(filter, { $set: upObj }, function (err, data) { if(err) { console.log(`Record could not updated with for ${serchKeyVal}`); console.log('Error while updating record====> ', err); reject(err); } else { if(data.result.nModified === 1) { console.log(`Record updated successfully for ${serchKeyVal}`); } else { console.log(`No matched record/No new value to update for ${serchKeyVal}`); } resolve(data); } }); });
修改后,每次迭代都会等待当前数据库更新完成并打印状态后,再处理下一条记录,消息将按迭代顺序逐条输出。
内容的提问来源于stack exchange,提问作者subhra_user
相关产品推荐
相关产品推荐

