迁移Express campground路由到controllers后报Route.get()回调错误
问题根因与排查方案
报错Route.get() requires a callback function but got a [object Promise]的核心触发逻辑,是传给Express路由的回调参数不符合规范——它本该是一个可被路由系统执行的函数,实际却是一个提前生成的Promise对象,按以下步骤排查即可定位解决:
- 检查Controller模块的导入导出逻辑
迁移路由处理代码到独立controllers文件后,这类问题90%以上和导出/导入的错漏有关:- 确认导入路径精确指向具体的controller实现文件,不要错误指向文件夹根路径,避免拿到整个模块对象而非单独导出的方法集合
- 确认controller文件中每个对外暴露的方法是方法定义,而非执行后的返回值:错误写法比如
exports.index = (async (req, res) => {})(),这种写法会直接执行async函数,拿到的就是Promise;正确写法为方法赋值的形式exports.index = async (req, res) => { ... }
- 校验
CatchAsync工具函数的实现CatchAsync的作用是包裹异步路由方法,自动捕获异步流程中抛出的错误,本质是一个接收函数、返回函数的高阶工具,最常见的实现错误是提前执行了传入的异步方法:
错误实现示例:
正确实现需要保证返回值是符合Express路由规范的回调,由Express在路由匹配时再触发内部的异步方法执行:// 错误逻辑:直接执行传入的fn,返回的是fn的执行结果(Promise) const CatchAsync = (fn) => fn()// 正确逻辑:返回标准格式的路由回调,内部再执行传入的异步方法 const CatchAsync = (fn) => (req, res, next) => { Promise.resolve(fn(req, res, next)).catch(err => next(err)) } - 快速定位的调试技巧
在路由注册代码前添加两行日志,可1分钟缩小问题范围:- 打印
typeof Campgrounds.index,如果返回值不是function,说明问题出在Controller的导入/导出环节 - 打印
typeof CatchAsync(Campgrounds.index),如果返回值不是function,说明问题出在CatchAsync的实现环节
- 打印
内容的提问来源于stack exchange,提问作者Ahmad Khalafalla
相关产品推荐
相关产品推荐

