express make try/catch block 放入中间件避免重复

Express make try/catch block into middleware to avoid duplication

我正在编写我的 expressJs 应用程序,我在我的路由控制器中发现了相同的重复代码来捕获异常,我想知道如何避免这种情况。

我已经检查过这个线程,但是我得到这个错误 "Cannot read property 'catch' of undefined" : Express Try and Catch in Form of middleware

这是我的route.js

const express = require("express");
const createHttpError = require("http-errors");
const Validator = require("../middlewares/Validator");
const TaskNotFoundException = require("../services/TaskNotFoundException");
const TaskService = require("../services/TaskService");

router.get("/tasks", async (req, res, next) => {
  try {
    const data = await TaskService.getTasks();
    res.send({ code: 200, message: "Success", data });
  } catch (error) {
    next(createHttpError(500));
  }
});

router.get("/task/:id", async (req, res, next) => {
  const { id } = req.params;
  try {
    const data = await TaskService.getTask(id);
    res.send({ code: 200, message: "Success", data });
  } catch (error) {
    if (error instanceof TaskNotFoundException) {
      next(createHttpError(404));
    } else {
      next(createHttpError(500));
    }
  }
});
and the list goes on

正如您在我的所有路线中看到的那样,我有一个带有可能错误的 try catch 块(只有 500 或 500/404)。我想避免这种重复。

这是我的app.js

const express = require("express");
const bodyParser = require("body-parser");
const createHttpError = require("http-errors");
const api = require("./routes/api");

const app = express();
app.use(express.json());
app.use(bodyParser.json());
app.use("/api", api);

// Catch HTTP 404
app.use((req, res, next) => {
  next(createHttpError(404));
});

// Error Handler
app.use((err, req, res, next) => {
  res.status(err.status || 500);
  res.json({
    error: {
      status: err.status || 500,
      message: err.message,
    },
  });
});

module.exports = app;

就像我说的,它现在工作得很好,我只是想尽量避免 try catch 代码重复,我已经检查了 Whosebug 中的其他问题,但没有帮助。该解决方案已将 returns 500 与此捕获未定义消息(这不是我想要的)相关联,并且在其他也有 404 的路由上它只是不起作用。

非常感谢!


更新: 我听从了 Heikos 的建议,但仍然无法正常工作

api.js

const express = require("express");
const createHttpError = require("http-errors");
const Validator = require("../middlewares/Validator");
const TaskNotFoundException = require("../services/TaskNotFoundException");
const TaskService = require("../services/TaskService");

const router = express.Router();

router.get("/tasks", async (req, res, next) => {
  const data = await TaskService.getTasks();
  res.send({ code: 200, message: "Success", data });
});

app.js

const express = require("express");
const bodyParser = require("body-parser");
const createHttpError = require("http-errors");
const api = require("./routes/api");

const app = express();
app.use(express.json());
app.use(bodyParser.json());

app.use("/api", api);

function catchAsyncErrors(middleware) {
  return async function(req, res, next) {
    try {
      await middleware(req, res, next);
    } catch(err) {
      next(err);
    }
  };
}

// Catch HTTP 404
app.use(catchAsyncErrors((req, res, next) => {
  next(createHttpError(404));
}));



// Error Handler
app.use(catchAsyncErrors((err, req, res, next) => {
  res.status(err.status || 500);
  res.json({
    error: {
      status: err.status || 500,
      message: err.message,
    },
  });
}));

module.exports = app;

如果异步中间件函数中的代码包含 await,您还必须将其包装在 try-catch 块中,否则拒绝的承诺将无法处理。例如:

app.use(async function(req, res, next) {
  try {
    await Promise.reject("error");
  } catch(err) {
    next(err);
  }
});

将错误传播到错误处理程序,但如果没有 try-catch 块,它会导致“UnhandledPromiseRejection”。

如果将中间件包装到 catchAsyncErrors 函数中,您可以节省一些输入:

function catchAsyncErrors(middleware) {
  return async function(req, res, next) {
    try {
      await middleware(req, res, next);
    } catch(err) {
      next(err);
    }
  };
}
router.get("/tasks", catchAsyncErrors(async (req, res, next) => {
  const data = await TaskService.getTasks();
  res.send({ code: 200, message: "Success", data });
}));