Javascript 如何在Sequelize(Node js)中关联对象?
我在Sequalize中有用户和文件模型。用户可以有多个文件。 我有联系 hasMany(db.File,{as:'Files',foreignKey:'userId',constraints:false}) 我想用几个文件初始化用户对象并将其保存到数据库中 我编写了下一个代码:Javascript 如何在Sequelize(Node js)中关联对象?,javascript,node.js,postgresql,sequelize.js,Javascript,Node.js,Postgresql,Sequelize.js,我在Sequalize中有用户和文件模型。用户可以有多个文件。 我有联系 hasMany(db.File,{as:'Files',foreignKey:'userId',constraints:false}) 我想用几个文件初始化用户对象并将其保存到数据库中 我编写了下一个代码: var files = []; var file1 = models.File.build(); file1.name = "JPEG"; file1.save()
var files = [];
var file1 = models.File.build();
file1.name = "JPEG";
file1.save().then(function () {
});
files.push(file1);
var file2 = models.File.build();
file2.name = "PNG";
file2.save().then(function () {
});
files.push(file2);
var newUser = models.User.build();
newUser.email = email;
newUser.save().then(function (usr) {
files.forEach(function (item) {
newUser.addFile(item);
});
});
但我发现了一个bug,有时几个文件与用户没有关联
我在nodejs日志中找到了用于为这些文件设置外键的命令(update)。
但命令没有执行。几个文件的外键(userId)为空
我认为问题在于异步查询。
如何组织代码结构以避免此错误?问题正是您所认为的异步代码 您需要在回调中移动函数,否则代码会在创建文件之前运行 JavaScript不会等待下一行,因此无论是否完成,它都会运行下一行。它没有在移动前等待的感觉 因此,您基本上是在添加一些尚不存在的内容,因为它不会等待文件保存后再继续 不过,只要将代码移到
调用中,然后将回调中,这就行了:
var files = [];
var file1 = models.File.build();
file1.name = "JPEG";
file1.save().then(function () {
files.push(file1);
var file2 = models.File.build();
file2.name = "PNG";
file2.save().then(function () {
files.push(file2);
var newUser = models.User.build();
newUser.email = email;
newUser.save().then(function (usr) {
files.forEach(function (item) {
newUser.addFile(item);
});
});
});
});
但那太乱了。相反,您可以像这样连锁承诺:
var files = [];
var file1 = models.File.build();
file1.name = "JPEG";
file1.save()
.then(function(file1) {
files.push(file1);
var file2 = models.File.build();
file2.name = "PNG";
return file2.save();
})
.then(function(file2) {
files.push(file2);
var newUser = models.User.build();
newUser.email = email;
return newUser.save();
})
.then(function(newUser) {
files.forEach(function(item) {
newUser.addFile(item);
});
});
var co = require('co');
co(function*() {
var files = [];
var file1 = models.File.build();
file1.name = "JPEG";
yield file1.save();
files.push(file1);
var file2 = models.File.build();
file2.name = "PNG";
yield file2.save();
files.push(file2);
var newUser = models.User.build();
newUser.email = email;
newUser.save();
files.forEach(function(item) {
newUser.addFile(item);
});
});
现在这是一个有点干净,但仍然有点混乱,也有点混乱。因此,您可以使用以下生成器函数:
var files = [];
var file1 = models.File.build();
file1.name = "JPEG";
file1.save()
.then(function(file1) {
files.push(file1);
var file2 = models.File.build();
file2.name = "PNG";
return file2.save();
})
.then(function(file2) {
files.push(file2);
var newUser = models.User.build();
newUser.email = email;
return newUser.save();
})
.then(function(newUser) {
files.forEach(function(item) {
newUser.addFile(item);
});
});
var co = require('co');
co(function*() {
var files = [];
var file1 = models.File.build();
file1.name = "JPEG";
yield file1.save();
files.push(file1);
var file2 = models.File.build();
file2.name = "PNG";
yield file2.save();
files.push(file2);
var newUser = models.User.build();
newUser.email = email;
newUser.save();
files.forEach(function(item) {
newUser.addFile(item);
});
});
现在好多了
仔细看,你会看到发生了什么co
接受一个生成器函数,该函数基本上是一个带星号的常规函数*
。这是一个特殊的函数,它添加了yield
表达式支持
yield
表达式基本上是等待调用then()
回调,然后再继续,如果then
回调有一个参数,那么它也会返回它
因此,您可以执行以下操作:
var gif = yield models.File.create({
name: 'gif'
});
而不是:
models.File.create({
name: 'gif'
}).then(function(gif) {
});
为此,您必须使用名为co
的小节点模块,尽管只需npm安装--save co
为什么不在用户之后创建文件,并在文件定义中添加用户Id?