module.exports中调用async.retry重试时抛出无效参数错误求助
解决async.retry抛出"Invalid arguments"错误的问题
我看到你遇到的问题了,咱们一步步拆解根源并修复:
核心错误原因
1. 错误传递任务函数给async.retry
你当前代码里写的是:
async.retry({ times: 3, interval: 200 }, module.exports.sendEnergy(url, body), function (err, result) { ... })
这里module.exports.sendEnergy(url, body)是直接执行了函数,而不是传递一个可被重试调用的函数引用。sendEnergy执行后返回undefined(因为你没写return),async.retry拿到undefined就会抛出"参数无效"的错误。
2. sendEnergy未遵循异步流程规范
async.retry要求重试的任务函数必须满足以下两种规范之一:
- 接受一个回调参数(
function(callback) { ... }),在异步操作完成时调用callback(err, result)传递结果/错误; - 返回一个Promise,让async.retry可以等待异步操作完成。
而你现在的sendEnergy里,request.post的回调只是内部处理逻辑,没有把错误或结果传递出去,async.retry根本感知不到异步操作的完成状态,也捕获不到错误。
修复后的代码
我给你两种实用方案,选你习惯的风格即可:
方案1:用Promise封装sendEnergy(推荐)
先安装request-promise(request已被官方弃用,也可以换成axios/node-fetch这类现代库),然后修改代码:
const rp = require('request-promise'); // 先执行 npm install request-promise module.exports = { sendMessageToNewModel: (body, id) => { let url = ''; switch (id) { case 'energy': url = 'http://myapi.test.api/appliance'; break; case 'device-energy': url = 'http://myapi.test.api/device'; break; default: // 增加默认分支避免url为空 throw new Error('Invalid id provided'); } // 用箭头函数包裹,确保每次重试都会重新调用sendEnergy async.retry({ times: 3, interval: 200 }, () => module.exports.sendEnergy(url, body), function (err, result) { if (err) { console.error('所有重试均失败:', err); return; } console.log('请求成功:', result); }); }, sendEnergy: (url, body) => { const options = { url: url, json: true, body: body, resolveWithFullResponse: true // 配置后可拿到完整响应对象 }; // 返回Promise,async.retry会自动处理异步流程 return rp.post(options) .then(res => res.statusCode) .catch(err => { // 抛出错误让async.retry捕获并重试 throw err; }); } }
方案2:用回调风格适配async.retry
如果你不想用Promise,也可以修改sendEnergy接受回调参数:
const request = require('request'); module.exports = { sendMessageToNewModel: (body, id) => { let url = ''; switch (id) { case 'energy': url = 'http://myapi.test.api/appliance'; break; case 'device-energy': url = 'http://myapi.test.api/device'; break; default: throw new Error('Invalid id provided'); } // 传递带callback的函数给async.retry async.retry({ times: 3, interval: 200 }, function(callback) { module.exports.sendEnergy(url, body, callback); }, function (err, result) { if (err) { console.error('所有重试均失败:', err); return; } console.log('请求成功:', result); }); }, sendEnergy: (url, body, callback) => { const options = { url: url, json: true, body: body }; request.post(options, (err, res, body) => { if (err) { // 将错误传递给callback,让async.retry捕获并重试 return callback(err); } // 将成功结果传递给callback callback(null, res.statusCode); }); } }
额外提示
- 变量
url记得用let声明,避免变成全局变量引发意外问题; - 重试间隔200秒偏长,一般API重试间隔设置为几秒到几十秒即可,你可以根据实际场景调整;
- request库已被官方标记为弃用,建议逐步迁移到axios、node-fetch等维护活跃的库。
内容的提问来源于stack exchange,提问作者lousybear
相关产品推荐
相关产品推荐

