如何修复未调用Express错误处理程序的问题



我知道这个问题又被重复了。我已经考虑过其他解决方案并尝试过了。我很感激你帮我调试这个问题。

我有一个单独的errorHandler作为中间件。

error-handler.ts:

import express, { Request, Response, NextFunction } from "express";
export const errorHandler = (
err: Error, 
req: express.Request, 
res: express.Response, 
next: express.NextFunction
) => {
console.log('Something went wrong');
res.status(400).send({
message: err.message
});
}

index.ts:

import express, { Request, Response, NextFunction } from 'express';
import { json } from 'body-parser';
import { currentUserRouter } from './routes/current-user';
import { signinRouter } from './routes/signin';
import { signoutRouter } from './routes/signout';
import { signupRouter } from './routes/singup';
import { errorHandler } from './middlewares/error-handlers';
const app = express();
app.use(json());
app.use(currentUserRouter);
app.use(signinRouter);
app.use(signoutRouter);
app.use(signupRouter);
app.use(errorHandler);
app.listen(3000, () => {
console.log('Listening on port 3000!!!');
})

当抛出Error时,Express没有捕捉到它。

注册.ts:

import express, { Request, Response } from "express";
const router = express.Router();
import { body, validationResult } from "express-validator";
const bodyValidation = [
body('email')
.isEmail()
.withMessage('Email must be valid'),
body('password')
.trim()
.isLength({ min: 4, max: 20})
.withMessage('Password must be between 4 and 20 characters')
];
router.post('/api/users/signup', bodyValidation, async (req: Request, res: Response) => {
const errors = validationResult(req);
if(!errors.isEmpty()) {
throw new Error('Invalid email or password');
}

console.log('Creating a user...');
res.send({});
});
export { router as signupRouter }

我可以看到正在抛出的终端中的Error: Invalid email or password。但Express并没有捕捉到抛出的错误。

Express不会注意路由处理程序的返回值。您将一个async函数传递给router.post,这意味着您的函数将返回一个报告其完成情况的承诺,而不是以通常的同步方式报告它。因此,函数中抛出的任何错误都会通过promise报告,而Express会忽略它。

通常,如果某个东西(在本例中为Express)不支持处理函数返回的Promise,那么将async函数作为回调传递给该东西不是一个好主意。

在您的示例中,没有任何使用await的代码,所以您可以删除async

如果你有使用await的代码,而你遗漏了这些代码来保持问题的简洁性(这是完全合理的),你可能会将其作为一个内部函数调用,并使用来自的promise

router.post("/api/users/signup", bodyValidation, (req: Request, res: Response) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
throw new Error("Invalid email or password");
}
console.log("Creating a user...");
(async () => {
// ...your code using `await` here...
// You're all done, send the result
res.send({});
})().catch((error) => {
// ...send error response...
});
});

请注意,该代码是如何捕获promise拒绝以便发送错误响应的——您不希望只处理promise拒绝。

另一种方法是确保该内部函数的整个主体位于try/catch:中

router.post("/api/users/signup", bodyValidation, (req: Request, res: Response) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
throw new Error("Invalid email or password");
}
console.log("Creating a user...");
(async () => {
try {
// ...your code using `await` here...
// You're all done, send the result
res.send({});
} catch (error) {
// ...send error response...
}
})();
});

最新更新