Express路由触发ESLint规则@typescript-eslint/no-misused-promises报错求助
问题排查:@typescript-eslint/no-misused-promises 错误分析
问题描述
执行ESLint脚本时,所有使用isAValidToken作为中间件的Express路由均抛出以下错误:
error Promise returned in function argument where a void return was expected @typescript-eslint/no-misused-promises
相关代码示例:
路由代码
import { getAllCards } from '../controllers/CardsController'; import express from 'express'; import { isAValidToken } from '../controllers/TokenController'; import { errorCallback } from '../controllers/ErrorController'; const router = express.Router(); router.get('/', isAValidToken, async (req, res) => { try { const cards = await getAllCards(); res.json(cards); } catch (error: any) { errorCallback(error, res); } });
TokenController核心代码
import jwt from 'jsonwebtoken'; import { API_SECRET } from '../constants/constants'; import { Request, Response, NextFunction } from 'express'; async function verifyAnyToken (token: string, secret: string): Promise<unknown> { return await new Promise((resolve, reject) => { jwt.verify(token, secret, (error) => { if (error != null) { reject(error); } else { resolve(token); } }); }); } async function verifyToken (token: string): Promise<unknown> { return await verifyAnyToken(token, API_SECRET); } export async function getTokenFromRequest (req: Request): Promise<string> { const token = req.body.token || req.headers['x-access-token'] || req.headers.authorization || req.params.token; return await getNormalizedToken(token); } export async function isAValidToken (req: Request, res: Response, next: NextFunction): Promise<void> { const token = await getTokenFromRequest(req); await verifyToken(token); next(); }
错误原因
- Express中间件的预期行为:Express的中间件函数默认期望是同步函数,或者返回
void——它不会自动处理中间件返回的Promise。 - async函数的特性:
isAValidToken被定义为async函数,这类函数无论是否显式返回值,都会默认返回一个Promise。 - ESLint规则触发:
@typescript-eslint/no-misused-promises规则会检测到「将返回Promise的函数当作期望返回void的回调使用」的场景,因此抛出错误。
另外,当前代码还存在隐藏风险:如果verifyToken抛出错误,这个Promise的rejection不会被捕获,会导致未处理的Promise拒绝错误,进而使服务器崩溃。
解决方案
方案一:正确处理异步中间件的错误
修改isAValidToken,手动捕获异步逻辑的错误并传递给Express的错误处理中间件,确保Promise的状态被正确处理:
export async function isAValidToken (req: Request, res: Response, next: NextFunction): Promise<void> { try { const token = await getTokenFromRequest(req); await verifyToken(token); next(); } catch (error) { // 将错误传递给Express全局错误处理中间件 next(error); } }
此时可以保留async函数,因为我们已经正确处理了所有可能的错误,ESLint不会再触发该规则(若仍触发,可在ESLint配置中对Express中间件场景放宽该规则)。
方案二:转换为回调风格的同步中间件
如果偏好Express传统的回调模式,可以将异步逻辑包装为链式调用,避免返回Promise:
export function isAValidToken (req: Request, res: Response, next: NextFunction): void { getTokenFromRequest(req) .then(token => verifyToken(token)) .then(() => next()) .catch(error => next(error)); }
这种方式下函数返回void,完全符合Express中间件的预期,ESLint规则不会触发。
内容的提问来源于stack exchange,提问作者Daniel Corona
相关产品推荐
相关产品推荐

