Почему mon goose работает асинхронно при создании и обновлении документа? - PullRequest
1 голос
/ 16 марта 2020

В следующей функции после создания документа work я сохраняю изображения из запроса, полученного через модуль multer. При сохранении документов image я пытаюсь обновить обработайте документ нажатием всех _id изображений.

Но каким-то образом, если вы посмотрите на приведенный ниже код и сосредоточитесь на console.log s второй console.log выполняется первым, хотя я использовал .then при создании изображений. Это также означает, что я получаю устаревший work документ в последние строки кода.

В документах говорится, что Model.create () возвращает Promise , что означает, что оно должно выполняться синхронно, если я использую . тогда () (если я не ошибаюсь). Но это не так в моей функции:

function addToDB(req, res, model) {
    let imagesToAdd = [];
    Works.create(model)
    .then(work => {
        req.files.forEach(image => {
            let path = image.path.split('').map(char => char === '\\' ? '/' : char).join('');
            let imageObj = {
                fileName: image.filename,
                mimeType: image.mimetype,
                imageURL: `${req.baseURL}/${path}`,
                workId: work._id
            };

            imagesToAdd.push(imageObj);
        });

        Images.create(imagesToAdd)
        .then(createdImages => {
            let imageIds = [];
            createdImages.forEach(image => {
                console.log(image._id);
                imageIds.push(image._id);
            });
            Works.updateMany({_id: work._id}, {$push: {images: {$each: imageIds}}}).catch(err => handleError(err));
        })
        .catch(err => handleError(err));
        console.log('>'+work._id);
        return work._id;
    })
    .then(workId => {
        Works.findById(workId)
        .then(foundWork => {
            res.json(foundWork);
        })
        .catch(err => handleError(err));
    })
    .catch(err => handleError(err));
}

А вот консоль после отправки работы документ:

cmd после выполнения:

enter image description here

И есть ответ:

Ответ после выполнения:

enter image description here

Там было добавлено 2 изображения. Выше в ответ вы видели, что массив images не имеет никакого элемента, а в пн go идентификаторы изображений были сохранены:

Сохраненная работа после выполнение:

enter image description here

Конечная цель - ответить только что созданной работой , в которую включены идентификаторы изображений, поэтому я можно дополнительно заполнить массив images документа work и workId в документе image .

Как можно заставить код работать синхронно?

1 Ответ

0 голосов
/ 16 марта 2020

Проблема в том, что:

Images.create(imagesToAdd)
    .then(createdImages => {
        let imageIds = [];
        createdImages.forEach(image => {
            console.log(image._id);
            imageIds.push(image._id);
        });
        Works.updateMany({_id: work._id}, {$push: {images: {$each: imageIds}}}).catch(err => handleError(err));
    })

настроен на асинхронный запуск, затем выполняется:

console.log('>'+work._id);
return work._id;

, вы go переходите к следующему then, и через некоторое время возвращается результат первого обещания.

Правильный путь будет следующим:

 function addToDB(req, res, model) {
let imagesToAdd = [];
Works.create(model)
.then(work => {
    // Populate imagesToAdd
    req.files.forEach(image => {
        let path = image.path.split('').map(char => char === '\\' ? '/' : char).join('');
        let imageObj = {
            fileName: image.filename,
            mimeType: image.mimetype,
            imageURL: `${req.baseURL}/${path}`,
            workId: work._id
        };
        imagesToAdd.push(imageObj);
    });

    Images.create(imagesToAdd)
    .then(createdImages => {
        // images have been created
        let imageIds = [];
        createdImages.forEach(image => {
            console.log(image._id);
            imageIds.push(image._id);
        });
        // imageIds has been populated
        Works.updateMany({_id: work._id}, {$push: {images: {$each: imageIds}}})
        .then(() => {
            // After update is finished, findById
            Works.findById( work._id )
                .then( foundWork => {
                    // Return the work after it has been updated with images
                    res.json( foundWork );
                } )
                .catch( err => handleError( err ) );
        })
        .catch(err => handleError(err));
    })
    .catch(err => handleError(err));
})
.catch(err => handleError(err));                }

Еще более простой способ - использовать asyn c / await.

...