Mongoose与MongoDB:日期字段处理及更新截止日期避崩溃咨询
问题:Node.js/Express/MongoDB应用批量更新任务截止日期时崩溃
我正在开发基于Node.js、Express、Mongoose和MongoDB的应用,需实现任务截止日期每24小时自动刷新功能,但更新时应用崩溃。
相关代码
Task.js(模型)
const mongoose = require('mongoose'); const taskSchema = new mongoose.Schema({ name: { type: String, required: true }, description: { type: String, required: true }, dueDate: { type: Date, required: true }, assignedTo: { type:mongoose.Schema.Types.ObjectId, ref: 'User' }, status: { type: Boolean, default: false }, })
taskControllers.js
const updateDueDate = async (req, res) => { const { dueDate } = req.body; if (!dueDate || isNaN(new Date(dueDate).getTime())) { return res.status(400).json({ message: 'Invalid due date' }); } try { const tasks = await Task.find({}); await Promise.all(tasks.map(async (task) => { task.dueDate = new Date(dueDate); await task.save(); }).catch(err => { return res.status(400).json({ err: err.message }); })); res.status(200).json({ message: 'Duedates updated }); } catch (err) { console.error('Error updating due dates:', err); res.status(500).json({ message: 'Error updating duedates', error: err.message }); } };
TaskDetails.js(前端)
useEffect(() => { const fetchTasks = async () => { try { const response = await axios.get('/api/users/{user.id}/tasks'); setDailyTasks(response.data.tasks); } catch (error) { console.error('Error fetching tasks:', error); } }; fetchTasks(); }, [setDailyTasks]); useEffect(() => { const refreshDueDate = async () => { const newDueDate = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(); try { const response = await axios.put(`/api/tasks/due`, { dueDate: newDueDate }); setDailyTasks(prevTasks => prevTasks.map(task => ({ ...task, dueDate: newDueDate, }))); console.log('Duedate updated!', response.data); } catch (error) { console.error('Error updating duedate', error); } }; const interval = setInterval(refreshDueDate, 24 * 60 * 60 * 1000); refreshDueDate(); return () => clearInterval(interval); }, [setDailyTasks]);
报错信息
更新时应用崩溃,日志显示:
SyntaxError: Unexpected end of JSON input at JSON.parse () MongoError: BSONError: input must be a 24 character hex string, 12 byte Uint8Array, or an integer
问题
- 如何确保日期格式正确并安全保存至MongoDB,避免崩溃?
- 有没有更优的日期更新方式,规避BSON格式问题?
- 在Mongoose和MongoDB中管理日期字段,我是否遗漏了最佳实践?
已尝试方案
- 确认Mongoose Schema中dueDate字段为Date类型;
- 将日期转为ISO字符串后发送至后端;
- 添加详细错误日志定位故障。
解决方案
1. 修复致命错误,确保日期安全保存
先解决导致崩溃的直接问题:
修复JSON语法错误:
taskControllers.js中响应的JSON字符串未闭合,改为:res.status(200).json({ message: 'Duedates updated' });这个错误会直接引发前端解析响应时的
SyntaxError。修正Promise错误处理位置:将
catch绑定在Promise.all而非map方法后,避免数组混入错误处理返回值:await Promise.all(tasks.map(async (task) => { task.dueDate = new Date(dueDate); await task.save(); })).catch(err => { return res.status(400).json({ err: err.message }); });修复前端请求路径:将硬编码的
{user.id}改为模板字符串语法,确保请求URL有效:const response = await axios.get(`/api/users/${user.id}/tasks`);增强日期验证:优化后端验证逻辑,确保解析后的日期有效:
const parsedDate = new Date(dueDate); if (!dueDate || isNaN(parsedDate.getTime())) { return res.status(400).json({ message: 'Invalid due date' }); }
2. 更优的批量更新方式
当前逐个查询保存的方式效率低且易引发并发问题,改用updateMany批量更新,直接规避BSON相关错误:
const updateDueDate = async (req, res) => { const { dueDate } = req.body; const parsedDate = new Date(dueDate); if (!dueDate || isNaN(parsedDate.getTime())) { return res.status(400).json({ message: 'Invalid due date' }); } try { // 一次请求完成所有任务的截止日期更新 await Task.updateMany({}, { $set: { dueDate: parsedDate } }); res.status(200).json({ message: 'Duedates updated' }); } catch (err) { console.error('Error updating due dates:', err); res.status(500).json({ message: 'Error updating duedates', error: err.message }); } };
3. Mongoose/MongoDB日期管理最佳实践
Schema层添加日期验证:在Task模型中提前拦截无效日期:
dueDate: { type: Date, required: true, validate: { validator: function(v) { return !isNaN(v.getTime()); }, message: props => `${props.value} is not a valid date!` } }优先使用原生Date对象:始终以
Date类型存储日期,Mongoose会自动处理BSON转换,避免字符串存储带来的解析问题。后端定时任务替代前端轮询:前端
setInterval在页面关闭后失效,改用后端定时任务(如node-schedule)实现自动更新:const schedule = require('node-schedule'); // 每天凌晨自动更新所有任务截止日期 schedule.scheduleJob('0 0 * * *', async () => { const newDueDate = new Date(Date.now() + 24 * 60 * 60 * 1000); await Task.updateMany({}, { $set: { dueDate: newDueDate } }); console.log('Automatically updated task due dates'); });避免不必要的日期转换:Mongoose返回的日期会自动转为ISO字符串,前端可直接使用;后端接收ISO字符串时,
new Date()可直接解析为有效Date对象。
内容的提问来源于stack exchange,提问作者Nutan Nimkar
相关产品推荐
相关产品推荐

