使用node-schedule调度axios API调用失败,任务未执行的问题排查
问题排查与修复方案
1. 日期格式解析问题
node-schedule对带毫秒的ISO字符串(比如你传入的2023-03-30T01:48:46.962Z)解析可能存在兼容问题,直接传字符串会导致调度逻辑无法识别正确时间。
修复:把日期字符串显式转为Date对象,同时加有效性校验:
function scheduleApiCall(expirationDate, token, email) { console.log(expirationDate, token, email) const scheduleDate = new Date(expirationDate); // 校验日期是否合法 if (isNaN(scheduleDate.getTime())) { console.error('无效的过期日期:', expirationDate); return; } const job = schedule.scheduleJob(scheduleDate, async function () { console.log('Making API call'); try { const response = await axios.post( 'http://localhost:3000/getnoti', { title: 'SERVER NOTIFICATION', body: 'I am coming from server', token: token }, { headers: { 'Content-Type': 'application/json' } } ); console.log(response); } catch (error) { console.error(error); } }); }
2. 时区不匹配导致任务过期
如果你的服务器本地时区是UTC+8(比如北京时间),而传入的日期是UTC时间,当本地时间早于UTC日期时,调度时间实际已经过去,node-schedule会直接跳过执行。
修复:加个时间校验,确保调度时间在当前时间之后:
function scheduleApiCall(expirationDate, token, email) { console.log(expirationDate, token, email) const scheduleDate = new Date(expirationDate); const now = new Date(); if (scheduleDate <= now) { console.error('调度时间已过期:', scheduleDate); return; } const job = schedule.scheduleJob(scheduleDate, async function () { console.log('Making API call'); try { const response = await axios.post( 'http://localhost:3000/getnoti', { title: 'SERVER NOTIFICATION', body: 'I am coming from server', token: token }, { headers: { 'Content-Type': 'application/json' } } ); console.log(response); } catch (error) { console.error(error); } }); }
3. 异步回调的潜在问题
虽然node-schedule支持async回调,但可以先简化逻辑验证调度是否正常:
测试步骤:先换成同步回调,看是否能打印日志:
const job = schedule.scheduleJob(scheduleDate, function () { console.log('Making API call'); // 暂时注释axios调用,先确认调度触发 });
如果同步回调能正常触发,再逐步加回axios异步逻辑。
4. 任务被垃圾回收
如果scheduleApiCall执行完后,job变量被垃圾回收,会导致任务被取消。可以把任务存到全局容器里:
修复:
// 全局存储所有调度任务,避免被回收 const scheduledJobs = []; function scheduleApiCall(expirationDate, token, email) { console.log(expirationDate, token, email) const scheduleDate = new Date(expirationDate); if (isNaN(scheduleDate.getTime()) || scheduleDate <= new Date()) { console.error('无效或已过期的调度时间:', scheduleDate); return; } const job = schedule.scheduleJob(scheduleDate, async function () { console.log('Making API call'); try { const response = await axios.post( 'http://localhost:3000/getnoti', { title: 'SERVER NOTIFICATION', body: 'I am coming from server', token: token }, { headers: { 'Content-Type': 'application/json' } } ); console.log(response); // 执行完移除任务 const index = scheduledJobs.indexOf(job); if (index !== -1) scheduledJobs.splice(index, 1); } catch (error) { console.error(error); } }); scheduledJobs.push(job); }
额外验证建议
- 更新node-schedule到最新稳定版:
npm install node-schedule@latest - 用近未来时间测试(比如10秒后):
// 测试用例,10秒后触发 const testDate = new Date(Date.now() + 10000); scheduleApiCall(testDate.toISOString(), 'test-token', 'test@example.com');
内容的提问来源于stack exchange,提问作者Hack
相关产品推荐
相关产品推荐

