简体   繁体   English

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

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

In the following function, after creating the work document, I save the images from the request retrieved through multer module.When saving the image documents I try to update the work document by pushing all the _id s of the images.在以下函数中,创建工作文档后,我保存了通过 multer 模块检索到的请求中的图像。保存图像文档时,我尝试通过推送图像的所有_id来更新工作文档。

But somehow, if you take a look at the code bellow and focus on the console.log s, the second console.log is being executed first, although I used .then when creating the images.That also means that I get an outdated work document on the final lines of code.但不知何故,如果你看一下下面的代码并关注console.log s,第二个console.log将首先执行,尽管我在创建图像时使用了.then 。这也意味着我得到了一个过时的工作文档的最后几行代码。

The docs say that Model.create() returns a Promise , which means it should run synchronously if I use .then() (if I'm not mistaken).文档说Model.create()返回一个Promise ,这意味着如果我使用.then() (如果我没记错的话)它应该同步运行。 But this is not the case in my function:但在我的函数中情况并非如此:

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

And here is the console after POSTing a work document:这是发布工作文档后的控制台:

cmd after execution:执行后cmd:

在此处输入图片说明

And there is the response:有回应:

response after execution:执行后响应:

在此处输入图片说明

There 2 images were added.Above you saw in the response that images array doesn't have any element, while in mongo the image ids were saved:添加了 2 个图像。在响应中您看到图像数组没有任何元素,而在 mongo 中保存了图像 ID:

The saved work after execution:执行后保存的工作:

在此处输入图片说明

The end goal is to respond with the newly created work , which has the image ids included, so I can further populate the images array of the work document and workId in the image document.最终的目标是要与新创建的工作,这包括了图像的IDS响应,这样我就可以进一步填充图像文档中的工作文档和workId图像阵列。

How can I make the code run synchronously ?如何让代码同步运行?

The problem is that this:问题在于:

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

is set to run asynchronously, then this:设置为异步运行,然后:

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

is executed, you go to the next then , and after some time the result of the first promise is returned.执行后,您转到下一个then ,一段时间后返回第一个 promise 的结果。

The correct way would be:正确的方法是:

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

Even simpler way is to use async / await.更简单的方法是使用 async / await。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM