javascript - 如何在 Sequelize (Node js) 中关联对象?

标签 javascript node.js postgresql sequelize.js

我在 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/

相关文章:

PostgreSQL 向现有行添加更多值

javascript - 当在 onClick 处理程序上使用 map 时,内部函数总是获取最后一个元素

javascript - 如何制作一个 NodeJS 服务器,在连接时按时间间隔逐行发出字符串文件?

node.js - NodeJS + Express + Socket.IO + SSL

node.js - Cloud9 安装问题

regex - PostgreSQL 正则表达式

javascript - 如何修复 Node.JS 和 Socket.io 中玩家定位关闭的问题

javascript - 两个 JavaScript 函数 onsubmit 和 onclick

javascript - Rhino 和 Javascript 1.8?

php - 未定义表 : 7 ERROR: relation "expenses" does not exist