Объединение множества маршрутов с использованием одного оператора switch - PullRequest
0 голосов
/ 09 июля 2019

Я создаю приложение для производственного использования и хотел бы объединить несколько маршрутов с помощью одного оператора 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}
}

1 Ответ

0 голосов
/ 09 июля 2019

Две проблемы:

  • Эта одна функция будет иметь тенденцию становиться довольно большой со временем. Имейте в виду, вы уже разделили логику на отдельные функции (я вернусь к этому через минуту).
  • Сохранение пользователя и сохранение заказа - это принципиально разные операции, но если URL-адрес /save в любом случае, это усложняет ведение журнала, отчетность и т. Д. Разница (пользователь и порядок) скрывается в данных POST, а не в URL.

Если вы делаете , выполняете все это в одной функции, параметры маршрута могут решить проблемы с журналированием и т. Д. E.g.:

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), которое не понимает, что оно возвращает (обещание). Если вы сделаете это, вам, скорее всего, придется обернуть все тело в try / catch для обработки ошибок (если только некоторые обработчики промежуточных программ не обещают эти обработчики).

...