Вы смешиваете синхронный и асинхронный код.
Contract.findOne({ customerID: cid }).sort({version: 'descending'}).exec((err, doc) => {
if (!err && doc != null) {
var currentVersion = parseInt(doc.version);
nextVersion = currentVersion + 1;
}
});
Приведенный выше код фактически говорит: «Идите в базу данных, найдите один из этих объектов и всякий раз, когда это будет сделано в будущем, запускайте этот код, который находится в блоке exec».
Один из способов рассуждать об асинхронном коде из синхронного мышления - это обещаний .
Вот полупсевдо-реализация:
router.put('/:cid/contracts', (req, res) => {
var cid = req.params.cid;
return getTheMostRecentContract(cid)
.then(function(oldContract){
var nextVersion = oldContract.version +1;
if(!validateCustomerId(cid)){
return res.status(400).send('Bad Request - Invalid input!');
}
var contract;
var savePromises = [];
req.body.contract.forEach((item) => {
contract = new Contract({
customerID: cid,
startDate: item.startDate,
endDate: item.endDate,
conditions: item.conditions,
price: item.price,
author: item.author,
version: nextVersion
});
savePromises.push(contract.save());
});
return Promise.all(savePromises);
})
.then(function(resultOfAllSavePromises){
//rest of code here
}).catch(function(error){
console.log('Error is updating a new customer:' + JSON.stringify(err, undefined, 2));
return res.status(400);
})
});
function getTheMostRecentContract(cid) {
return Contract.findOne({ customerID: cid }).sort({version: 'descending'});
}
На практикеоднако, база данных должна контролировать ваши значения автоинкремента.Этот код не будет работать в условиях интенсивного трафика.