Expressjs не выполняется последовательно и функция return не работает - PullRequest
0 голосов
/ 08 октября 2018

Я новичок в узле / экспрессе js и пытаюсь выполнить следующее.Элемент управления выполняет строки после вызова функции «var nextVersion = getNextContractVersion (cid)», даже до того, как функция вернет ответ.В результате значение для newVersion не обновляется для объекта Contract.Кроме того, функция getNextContractVersion (cid) возвращает неопределенное значение, в отличие от обновленного nextVersion.

Как мне исправить это поведение, предложите.Кроме того, это правильный способ вызова функции?

// Package imports
const express = require('express');
var router = express.Router();
const mongoose = require('mongoose');

//Local imports
var { Customer } = require('../models/customer');
var { Contract } = require('../models/contract');

router.put('/:cid/contracts', (req, res) => {

    var cid = req.params.cid;

    var nextVersion =getNextContractVersion(cid);


    var contract;
    if (validateCustomerId(cid)) {
        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
            });

        });

        contract.save((err, docs) => {

            if (!err) {
                Customer.findOneAndUpdate({ customerID: cid }, { $push: { contract: contract } },
                    { safe: true, upsert: true, new: true }).populate({ path: 'contract' }).exec((err1, docs1) => {

                        if (!err1) {
                            res.send(docs1).status(200);
                        } else {
                            console.log('Error is adding a new contract:' + JSON.stringify(err1, undefined, 2));
                        }
                    });
            } else {
                console.log('Error is updating a new customer:' + JSON.stringify(err, undefined, 2));
            }

        });
    } else {
        res.status(400).send('Bad Request - Invalid input!')
    }

});



function getNextContractVersion(cid) {

    var nextVersion=1;


    Contract.findOne({ customerID: cid }).sort({version: 'descending'}).exec((err, doc) => {

        if (!err && doc != null) {

            var currentVersion = parseInt(doc.version);

            nextVersion = currentVersion + 1;

        } 

    });

    return nextVersion;
}

1 Ответ

0 голосов
/ 08 октября 2018

Вы смешиваете синхронный и асинхронный код.

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'});
}

На практикеоднако, база данных должна контролировать ваши значения автоинкремента.Этот код не будет работать в условиях интенсивного трафика.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...