使用express-asyncify返回HTTP状态码时报错Cannot read property 'send' of undefined
错误原因
- 路由修改后调用
myController.handle(req.params)时,仅传入了req.params一个参数,但控制器的handle方法定义需要接收req、res两个Express原生请求/响应对象,导致方法内的res变量为undefined,调用res.send时触发报错。 - 逻辑冲突:原有控制器的
handle方法已经内置了res.send响应逻辑,路由层又额外写了响应返回逻辑,二者重复且容易导致二次响应报错。 - 额外逻辑隐患:原有控制器中使用
req.url获取的是完整请求路径,如果你需要获取路由定义中:url对应的占位参数值,正确写法应为req.params.url,原有取值逻辑不符合需求。
修复方案
你可以根据自己的分层规划选择任意一种方案:
方案1:路由层统一处理错误和响应(推荐,职责分离更清晰)
改造控制器,去掉内部的响应逻辑,仅返回业务数据或抛出错误:
const testService = require('../services/testservice'); async function handler(url) { const result = await testService.HandleFile(url); return result; } // 改造为仅接收url参数,返回业务结果,错误直接抛出 const handle = async function (url) { const result = await handler(url); if (result === undefined) throw new Error('Invalid result!'); return result; }; module.exports = { handle, };
调整路由层的传参:
router.get('/:url', async (req, res) => { console.log(req.params); try { // 传入路由参数中的url值 const result = await myController.handle(req.params.url); res.status(200).send(result); } catch (err) { res.status(500).json({message: err.message}); } });
方案2:保留控制器原有响应逻辑,修改路由调用方式
不需要在路由层额外包装异步逻辑,直接将控制器方法作为路由回调,Express会自动注入req和res参数:
// 路由代码简化为 router.get('/:url', myController.handle)
如果需要在路由层加额外处理逻辑,要正确传递参数,同时调整控制器的错误处理逻辑(把return error改为throw error,否则路由层捕获不到异常):
// 调整后的控制器代码 const handle = async function (req, res) { try { // 改取路由参数的url const result = await handler(req.params.url); if (result === undefined) throw new Error('Invalid result!'); return res.send(result); } catch (error) { console.log(`An error had happened ${error.message})`); // 抛出错误交由路由层处理 throw error; } }; // 调整后的路由代码 router.get('/:url', async (req, res) => { console.log(req.params); try { // 正确传入req、res两个参数 await myController.handle(req, res); } catch (err) { res.status(500).json({message: err.message}); } });
内容的提问来源于stack exchange,提问作者Nooshin
相关产品推荐
相关产品推荐

