У меня есть приложение ExpressJS, которое принимает данные формы и выполняет следующие действия: 1. проверяет наличие всех необходимых значений, 2. проверяет правильность данных, 3. добавляет запись в базу данных для получения уникального идентификатора, 4. использует идентификатор и данные для вызова отдельного сервера, 5. после ответа от сервера обновить запись базы данных с подробностями ответа.
Я использую mongoskin для базы данных.
Мой вопрос касается того, как я контролирую поток. По сути, я написал каждый из вышеперечисленных шагов как функцию промежуточного программного обеспечения, потому что мне нужно вызывать next() в случае успеха (или next(err) в случае ошибки) при каждом обратном вызове.
Кажется, что я пишу слишком много промежуточного программного обеспечения и должен иметь возможность группировать шаги в более крупные наборы промежуточного программного обеспечения, содержащие несколько «подфункций», но я не уверен, как это сделать в Express, так как мне нужно вызвать next() каждый раз, когда завершается вызов асинхронной функции. Есть ли правильный способ сделать это или этот подход «одно промежуточное ПО на шаг» действительно правильный способ запустить это?
РЕДАКТИРОВАТЬ: Публикация некоторого кода по запросу. Это частичный код для краткости:
function validateFields(req, res, next) {
//...
//iterate over req.body to confirm all fields provided
//...
if (allDataProvided) {
//...
//iterate over req.body to confirm all fields valid
//...
if (allDataValid) {
return(next());
} else {
return(next(err));
}
} else {
return(next(err));
}
},
//get an auto incrementing ID fields from a mongodb collection (counters)
function getNextID(req, res, next) {
counters.findAndModify(
{ _id: "receiptid" },
[['_id','asc']],
{ $inc: { seq: 1 } },
{},
function(err, doc) {
if (err) {
return next(err);
} else {
req.receiptid = doc.seq;
return next();
}
});
},
//insert a new record into the transaction collection (txns) using the new ID
function createTransaction(req, res, next) {
txns.insert(
{ _id : req.receiptid,
body : req.body,
status : "pending"},
{},
function(err, r) {
if (err) {
return next(err);
} else {
return next();
}
});
},
//process the data on the remote web service using the provider's API (remoteapi)
function processTransaction(req, res, next) {
remoteapi.processTransaction(
{ data: req.body,
receiptid: req.receiptid },
function(err, r) {
if (err) {
return next(err);
} else {
req.txnReceipt = r;
return next();
}
});
},
//update the record in the database collection (txns) with the server response
function updateDatabase(req, res, next) {
txns.updateById(req.receiptid,
{ $set :{status : "success",
receipt: req.txnReceipt }
}, function (err, r) {
if (err) {
return next(err);
} else {
return next();
}
});
}
И в настоящее время с вышеупомянутыми функциями мой маршрут, который использует это промежуточное программное обеспечение, начинается так:
router.post('/doTransaction',
validateFields,
getNextID,
createTransaction,
processTransaction,
updateDatabase,
function(req, res, next) { //...
Кажется, что я должен быть в состоянии создать одну промежуточную функцию, которая выполняет все эти действия подряд без необходимости быть отдельным промежуточным программным обеспечением, но поскольку каждое промежуточное программное обеспечение имеет в нем асинхронную функцию, и мне нужно вызвать next() в полученный обратный вызов, это единственный способ, которым я вижу, как он работает.
Спасибо, Аарон.