Fastify配置多个preHandler钩子时控制器方法重复调用如何解决
问题诱因
- 核心原因是
autohooks.js的插件定义违反了Fastify的异步处理规范:该插件函数同时使用了async异步声明和next回调参数。Fastify对插件/钩子的异步处理遵循二选一规则:要么使用async/await语法(不传入next参数,等待Promise自动决议后推进流程),要么使用回调模式(传入next参数,手动调用next()推进流程)。两种模式混用后,async函数自动决议会触发一次流程推进,未被调用的next超时重试又会触发第二次流程推进,最终导致路由控制器被重复调用。 - 次要排查点:若你的
createClub不是工厂函数,调用createClub(fastify)时会直接执行控制器逻辑,加上请求到来时的第二次执行,也会出现调用两次的现象。
解决方案
- 修正
autohooks.js的插件代码,移除next参数,使用纯async/await写法:
const authentication = require('../../middlewares/authentication'); module.exports = async function (fastify, opts) { fastify.addHook('preHandler', authentication.authenticate(fastify)); };
- 检查
authentication.authenticate返回的preHandler钩子函数,同样不要混用async和next参数,确保每个钩子仅触发一次流程推进。 - 确认
createClub是标准的工厂函数,调用后返回路由处理函数而非直接执行逻辑,示例写法如下:
function createClub(fastify) { // 初始化逻辑仅在路由注册时执行一次 return async function (request, reply) { // 实际控制器逻辑写在返回的函数内,请求到来时才执行 const { name, description, logoUrl } = request.body; // 业务逻辑实现 // ... return { status: 'ok', data: newClub }; } }
内容的提问来源于stack exchange,提问作者HexaCrop
相关产品推荐
相关产品推荐

