[英]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.