【问题标题】:Wrapper for async handlers in Express with custom request propertiesExpress 中带有自定义请求属性的异步处理程序的包装器
【发布时间】:2019-02-25 15:33:10
【问题描述】:

正如https://strongloop.github.io/strongloop.com/strongblog/async-error-handling-expressjs-es7-promises-generators/#using-es7-asyncawait 所展示的,我想为我的所有异步 Express 处理程序使用一个包装器来捕获那里发生的任何错误,但在 TypeScript 的类型化版本中。

我想出了这个:(wrap.ts)

import { NextFunction, RequestHandler, Response, Request } from 'express';

type AsyncRequestHandler = (req: Request, res: Response, next: NextFunction) => Promise<any>;

/**
 * Catches errors and passes them to the next callback
 * @param handler Async express request handler/middleware potentially throwing errors
 * @returns Async express request handler with error handling
 */
export default (handler: AsyncRequestHandler): RequestHandler => {
  return (req, res, next) => {
    return handler(req, res, next).catch(next);
  };
};

我想构建一个带有一些端点的 REST API,例如 PUT /users/:userId 和 DELETE /users/:userId。为方便起见,我不想在每个处理程序的数据库中查询 ID 为 userId 的特定用户,而是使用中间件将其存储在 req 中。这意味着我必须使用修改后的Request 接口来添加user 属性的处理程序定义,例如UserRequest.

import express, { Request } from 'express';
import wrap from './wrap';

const app = express();

app.use('/users/:userId', wrap(async (req, res, next) => {
  // set req.user ...
}));

export interface UserRequest extends Request {
  user: User;
}

app.put('/users/:userId', wrap(async (req: UserRequest, res) => {
  // do something with req.user ...
}));

// ...

这在不使用wrap 时是可能的,但对于wrap 的这种类型定义则不行。 TypeScript 编译器产生以下错误:

Argument of type '(req: UserRequest, res: Response) => Promise<void>' is not assignable to parameter of type 'AsyncRequestHandler'.
  Types of parameters 'req' and 'req' are incompatible.
    Type 'Request' is not assignable to type 'UserRequest'.
      Property 'user' is missing in type 'Request'.

完成此任务的“TypeScript 方式”是什么?

【问题讨论】:

  • 我猜你必须使wrap 泛型而不是Request 类型
  • 谢谢。你能提示一下这是如何工作的吗?
  • 这样你就可以使用wrap&lt;UserRequest&gt;(async (req, res) =&gt; { … req.user …
  • 我可以重现错误的唯一方法是打开strictFunctionTypes,然后即使我不调用wrap,我也会在app.put 的参数上收到错误。如果我将wrap 设为通用,那么当包装的处理程序传递给app.put 时,我不会得到wrap 的参数错误,而是得到它。如果您使用strictFunctionTypes,则必须在某些时候协调UserRequest 和Request 之间的差异。例如,您可以使用一个单独的包装函数,该函数将采用UserRequest 的处理程序转换为采用Request 的处理程序。

标签: node.js typescript express asynchronous promise


【解决方案1】:

我不知何故没有意识到这个问题在没有wrap 的情况下也会出现(只要启用了strict 编译器选项)。我的解决方案是扩展express.Request 接口。

【讨论】:

    猜你喜欢
    • 2021-02-18
    • 2021-06-18
    • 2019-05-26
    • 1970-01-01
    • 2012-04-30
    • 2013-11-24
    • 1970-01-01
    • 1970-01-01
    • 2016-08-21
    相关资源
    最近更新 更多