Node.js / Sequelize.js / Express.js - 如何在多对多关联中进行插入?(同步/异步?)

8
我有两个模型(Individual,Email),正在尝试使用Sequelize命令插入到创建的“Individual_Email”表中。虽然Sequelize正在创建所需的表,但在尝试添加/获取/设置该表时返回以下错误:“Object [object Promise] has no method 'addEmail'”。我错过了什么?
Sequelize文档表示,如果模型为User和Project,“这将向Project添加getUsers,setUsers,addUsers方法,并向User添加getProjects,setProjects和addProject”。
这让我相信(查看承诺)我可能误解了如何使用Node的异步功能。我尝试了同步和异步版本的插入,两者都返回上述相同的消息。
Sequelize文档:http://docs.sequelizejs.com/en/latest/docs/associations/ 代码:
routes/index.js
var express = require('express');
var router = express.Router();
var models  = require('../models');

/* GET home page. */
router.get('/', function(req, res, next) {
    'use strict';

    var tIndividual, tEmail;
    tIndividual = models.Individual.create({
        name: "Test"
    });
    tEmail = models.Email.create({
        address: "test@gmail.com"
    });
    console.log(tEmail);

    res.render('index', { title: 'Express' });
});

module.exports = router;

或者

/* GET home page. */
router.get('/', function(req, res, next) {
    'use strict';

    var tIndividual, tEmail;    
    tIndividual = models.Individual.create({
        name: "Test"
    }).then(function(){
        tEmail = models.Email.create({
            address: "test@gmail.com"
        }).then(function(){
            tIndividual.addEmail(tEmail).then(function(){
                console.log("Success");
            });
        })
    });

    res.render('index', { title: 'Express' });
});

module.exports = router;

models/index.js

db.Individual.hasMany(db.Email, {
    as: 'Email',
    through: 'Individual_Email'
});
db.Email.hasMany(db.Individual, {
    as: 'Individual',
    through: 'Individual_Email'
});

我应该如何最好地添加到“Individual_Email”表中? 我假设我需要同步执行以等待更新,但我对任何建议都持开放态度。谢谢!

3个回答

10

当您调用.save().create()等返回Promise的方法时,应在该promise上调用.then()。当它被解决--即对象被保存/创建/其他操作时--您的then函数将被调用,并将收到已保存/创建的对象作为参数。

因此,您的第一次尝试可以重写为:

models.Individual.create({
  name: "Test"
}).then(function(createdIndividual) { // note the argument
  models.Email.create({
    address: "test@gmail.com"
  }).then(function(createdEmail) { // note the argument
    createdIndividual.addEmail(createdEmail)
      .then(function(addedEmail) { // note th-- well you get the idea :)
        console.log("Success");
      });
  })
});

上面的代码缺少一些重要的东西,例如返回承诺以便更好地链接和处理错误,但这是一个开始。我建议查看Bluebird文档(这是Sequelize使用的Promise库,但还有其他几个)


你能否一次性在创建邮件的同时添加while吗?而不是先创建再添加Email? - Morteza Shahriari Nia
请注意,此关联是N:M,因为个人和电子邮件都已配置为“hasMany”。因此最终有三个表(Emails、Individuals和EmailIndividual)。上述代码实际上将生成三个INSERT语句,因为有三个表需要填充,无法少于三个。 - st.never
@MortezaShahriariNia 话虽如此,我曾经遇到过类似的情况,并在这个问题中解决了它:http://stackoverflow.com/questions/28751483/is-there-a-shortcut-in-sequelize-for-user-setgroups-when-i-have-all-the-grou - st.never

2
您可以使用最佳方式的承诺来缓解“金字塔式嵌套”问题:
var createdIndividual;
models.Individual.create({
  name: "Test"
}).then(function(createdIn) { // note the argument
  createdIndividual = createdIn;
  return models.Email.create({
    address: "test@gmail.com"
  });
}).then(function(createdEmail) { // note the argument
  return createdIndividual.addEmail(createdEmail);
}).then(function(addedEmail) { // note th-- well you get the idea :)
  console.log("Success");
});

0

我找到了一种解决方法,但如果有更好的方法,请告诉我。

我的解决方案: 由于.create()返回一个Promise,我改用返回实例的.build(),并在两者都同步保存后才添加到“Individual_Email”。然后我调用从.build()返回的实例的add方法,并插入表格。

我的代码:

var tIndividual, tEmail;
tIndividual = models.Individual.build({
    name: "Test"
});
tEmail = models.Email.build({
    address: 'test@gmail.com'
});
tIndividual.save()
    .success(function(){
        tEmail.save()
        .success(function(){
            tIndividual.addEmail(tEmail);
        });
});

最好将 then 链接起来,而不是没有原因地嵌套它们。 - Benjamin Gruenbaum
嘿,你能在创建对象之前添加电子邮件吗?我这么问的原因是我想确保如果整个插入成功了,就继续进行,否则就不要在任何表中创建任何东西。 - Morteza Shahriari Nia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接