为快速路由器创建装饰器?

Creating decorators for express router?

为了使代码更加轻量和可读,我想到了为 express router 创建一个简单的装饰器。

发件人:

itemRouter
    .get('/:item_id', async (req, res, next) => {
        try {
            const id = parseInt(req.params.item_id)
            const item = await itemController.getItemById(id)
            res.status(StatusCodes.OK).send(item)
        } catch (error) {
            next(error)
        }
    })

接近这个最终结果的东西:

itemRouter
    .get('/:item_id',
            expressDecorator(async (req, res, next) => {
                const id = parseInt(req.params.item_id)
                return itemController.getItemById(id)
            })
    })

function expressDecorator(wrapped) {
    return function () {
        const { req, res, next } = arguments
        try {
            const { statusCode, bodyResponse } = wrapped.apply(this, arguments)
            res.status(statusCode).send(bodyResponse)
        } catch (error) {
            next(error)
        }
    }
}

但是我遗漏了一些东西,因为它根本不起作用。这是什么?

PS : 我完全知道有一个 express-router-decorator npm 包,但我希望自己做实验来了解它是如何工作的。

您原来的路由器控制器使用 async/await 语法。内部函数也应该使用 async/await

例如

const express = require('express');

const app = express();
const port = 3000;
const itemController = {
  getItemById(id) {
    return { statusCode: 200, bodyResponse: 'test_item_' + id };
  },
};

app.get(
  '/:item_id',
  expressDecorator(async (req, res, next) => {
    const id = parseInt(req.params.item_id);
    return itemController.getItemById(id);
  }),
);

function expressDecorator(wrapped) {
  return async function (...args) {
    const [req, res, next] = args;
    try {
      const { statusCode, bodyResponse } = await wrapped.apply(this, args);
      res.status(statusCode).send(bodyResponse);
    } catch (error) {
      next(error);
    }
  };
}

app.listen(port, () => console.log(`HTTP server started at http://localhost:${port}`));

测试通过 curl:

> curl http://localhost:3000/1


StatusCode        : 200
StatusDescription : OK
Content           : test_item_1
RawContent        : HTTP/1.1 200 OK
                    Connection: keep-alive
                    Keep-Alive: timeout=5
                    Content-Type: text/html; charset=utf-8
                    Date: Wed, 03 Feb 2021 02:32:02 GMT
                    ETag: W/"b-UjEymk+xUeSCTPOQ7NOHrxuV2as"...
Forms             : {}
Headers           : {[Connection, keep-alive], [Keep-Alive, timeout=5], [Co 
                    ntent-Length, 11], [Content-Type, text/html; charset=ut 
                    f-8]...}
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        : System.__ComObject