为什么 mongoose 运行 在创建和更新文档时异步?

Why does mongoose run asynchronously when creating and updating a document?

在下面的函数中,在创建 work 文档后,我保存了通过 multer module.When 检索到的请求中的图像,保存了 image 文档 我尝试通过推送图像的所有 _id 来更新 work 文档。

但是不知何故,如果你看一下下面的代码并关注 console.logs,第二个 console.log 首先被执行,尽管我在创建 images.That 时使用了 .then 也意味着我得到了一个过时的 work 关于最后几行代码的文档。

文档说 Model.create() returns 一个 Promise,这意味着它应该 运行 如果我使用 .then() 同步(如果我没记错的话)。但是在我的函数中不是这样的:

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

这是发布 work 文档后的控制台:

cmd 执行后:

并且有响应:

执行后响应:

有 2 张图像 added.Above 您在响应中看到 images 数组没有任何元素,而在 mongo 中图像 ID 是已保存:

执行后保存的工作:

最终目标是响应新创建的 work,其中包含图像 ID,因此我可以进一步填充 images work 文档的数组和 image 文档中的 workId

如何使代码 运行 同步?

问题在于:

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;

执行完,你去下一个then,一段时间后返回第一个promise的结果。

正确的方法是:

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

更简单的方法是使用异步/等待。