Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在Sequelize(Node js)中关联对象?_Javascript_Node.js_Postgresql_Sequelize.js - Fatal编程技术网

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

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()

我在Sequalize中有用户和文件模型。用户可以有多个文件。 我有联系 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日志中找到了用于为这些文件设置外键的命令(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?