我在 Sequlize 中有用户和文件模型。用户可以有多个文件。 我有联想 db.User.hasMany(db.File, {as: 'Files', foreignKey: 'userId', constraints: false});
我想用几个文件初始化用户对象并将其保存到数据库中。
我写了下一段代码:
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 日志中)为这些文件设置外键的命令(更新)。 但是命令没有执行。多个文件的外键(userId)为空。
我认为问题出在异步查询中。 如何组织代码结构来避免这个错误?
最佳答案
问题正是您所想的,异步代码。
您需要将函数移动到回调中,否则代码会在文件创建之前运行。
JavaScript 在移动到下一行之前不会等待,因此无论是否完成,它都会运行下一行。它没有移动前的等待感。
所以你基本上是在添加一些尚不存在的东西,因为它不会在继续之前等待文件被保存。
这会起作用,只需将代码移到 then
回调中:
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);
});
});
});
});
但这很困惑。相反,您可以像这样链接 promise :
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) {
});
虽然只是 npm install --save co
co
的小 Node 模块
关于javascript - 如何在 Sequelize (Node js) 中关联对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39855835/