使用一个 switch 语句组合多个路由

Combining many routes using one switch statement

我正在创建一个供生产使用的应用程序,并希望使用一个 switch 语句组合多个路由。我目前在开发中使用它并且它工作得很好,但是我以前没有看到过这种方法,并且想知道是否有原因。 使用这种方法有什么问题吗?如果是这样,真的要在答案中寻找 为什么

这就是我想要做的,而不是创建多条路线。

router.post('/save', auth, async (req, res)=>{
    switch(req.body.action) {
        case 'user':
            result = await asyncSaveUser(req.body.data);
            break;
        case 'order':
            result = await asyncSaveOrder(req.body.data);
            break;
        default:
            result = {success:false, data: 'not valid action'};
            break;     
    }
    return res.status(200).json(result);
})

在 API 我会创建一个动作。

url: {baseUrl}+'/save'
body: {
    "action":"user",
    "data": {"fn": John, "ln": Doe}
}

两个问题:

  • 随着时间的推移,这个函数往往会变得相当大。请注意,您已经将逻辑隔离到单独的函数中(稍后我会回过头来)。
  • 保存用户和保存订单是根本不同的操作,但是如果 URL 是 /save 无论哪种方式,都会使日志记录、报告等变得更加困难。差异(用户与订单)隐藏在 POST 数据中,而不是在 URL.

如果你在一个函数中做所有事情,route parameters可以解决日志记录等问题,关注。例如:

router.post('/users/:action', async function (req, res) { // Added `async`, since you're using `await`
    switch(req.params.action) {
        case 'user':
            result = await asyncSaveUser(req.body.data);
            break;
        case 'order':
            result = await asyncSaveOrder(req.body.data);
            break;
        default:
            result = {success:false, data: 'not valid action'};
            break;     
    }
    return res.status(200).json(result);
})

回到避免让这个函数变得过长:您可以使用调度对象:

const actionDispatch = {
    action: async asyncSaveUser(data) {
        // ...
    },
    user: async asyncSaveUser(data) {
        // ...
    }
};
function invalidAction() {
    return {success:false, data: 'not valid action'};
}

router.post('/users/:action', async function (req, res) {
    const actionFunction = actionDispatch[req.params.action] || invalidAction;
    const result = await actionFunction(req.body.data);
    return res.status(200).json(result);
});

当然,actionDispatch 对象可能会开始变长。你可能会把它分解得更多,缺点是维护(当它们在别处定义时必须列出其中的函数)。


旁注:谨防将 async 函数传递给不理解其内容的对象 (router.post) returns(承诺)。如果这样做,您几乎必须将整个主体包装在 try/catch 中以处理错误(除非这些处理程序有一些中间件处理承诺)。