嘿所以我对Javascript和Node很陌生,但是我遇到了困扰我一段时间的问题。
我有一个User模型和一个Image模型,我使用Multer上传一个图像数组, 试图遍历这个数组,为每个数组创建一个新的Image模型,然后取消该图像进入我用户的照片 。我让Multer成功填写了req.files。这是代码。
router.post("/users/:user/photos/upload", middle.isLoggedIn, upload.array("photos", 4), function(req, res) {
User.findById(req.params.user, function(err, foundUser) {
for(var i = 0, len = req.files.length; i < len; i++) {
Image.create(req.files[i], function(err, newImage) {
if(err) {
return console.log(err.message);
}
newImage.human = foundUser;
newImage.save();
console.log(newImage);
foundUser.photos.unshift(newImage);
foundUser.save();
});
}
console.log(foundUser);
});
});
console.log(foundUser);
似乎在console.log(newImage);
用户模型
var mongoose = require("mongoose"),
passportLocalMongoose = require("passport-local-mongoose");
var UserSchema = new mongoose.Schema({
username: String,
password: String,
firstName: String,
lastName: String,
city: String,
photos: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Image"
}
]
});
HumanSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", UserSchema);
图像模型
var mongoose = require("mongoose");
var ImageSchema = new mongoose.Schema({
fieldname: String,
originalname: String,
mimetype: String,
filename: String,
destination: String,
size: Number,
path: String,
human: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "Human"
}
}
});
module.exports = mongoose.model("Image", ImageSchema);
这是我的第一个stackoverflow问题,如果我没有发布足够的代码,请告诉我。
我认为它与Image.create()是异步的有关,我仍然在尝试更多地了解这个和承诺,但我仍然不完全理解它在我的代码中的相关性。
答案 0 :(得分:1)
Promise.all
允许您解析一系列承诺。
由于可以按任何顺序执行的异步代码,我不确定您的代码是否结构化而没有串行循环。我不确定在不同时间在同一个对象上触发多个foundUser.save()
会很好。长时间在内存中保存数据库对象也会打开更多的并发数据问题。
Bluebird承诺库包含一些额外的帮助程序,如Promise.each
,它们会在下次启动之前连续完成承诺,这可能会在这里使用。
const Promise = require('bluebird')
router.post("/users/:user/photos/upload", middle.isLoggedIn, upload.array("photos", 4), async function(req, res, next) {
try {
let foundUser = await User.findById(req.params.user)
await Promise.each(req.files, async file => {
let newImage = await Image.create(file)
newImage.human = foundUser;
await newImage.save()
console.log(newImage)
foundUser.photos.unshift(newImage)
await foundUser.save()
}
console.log(foundUser)
}
catch (err) {
next(err)
}
})
.map
和.reduce
等其他方法有助于使Promises的标准数组/循环类型操作更容易。
原子更新
关于并发问题,您可以在MongoDB中执行的任何“原子”更新都是一件好事。因此,不是选择一些东西,在JS中修改它,然后将其保存回来,而是将更新发送给Mongo并让db服务器处理它。无论您将更新发送到数据库的顺序如何,它们都将始终更新最新的数据副本。
在这种情况下,使用findByIdAndUpdate
和$push
可以在没有初始选择的情况下完成数组unshift
(可以使其在位置0处推进,没有{{1}在mongo)。
如果您为用户模型添加方法以添加照片:
$unshift
所以代码看起来像
addPhoto(user_id, newImage){
return User.findByIdAndUpdate(
user_id,
{ $push: { photos: { $each: [newImage], $position: 0 } } } }
{ safe: true, new: true }
)
}