Node.js / Sequelize.js / Express.js – Comment insérer dans plusieurs-à-nombreux association? (Synchronisation / async?)

J'ai deux modèles (Particulier, Email) et j'essaie d'insérer dans la table 'Individual_Email' créé en utilisant les commandes Sequelize. Alors que Sequelize crée la table souhaitée, elle renvoie l'erreur suivante lors de l'ajout / l'ajout / la définition de / vers cette table: "Object [object Promise] n'a pas de méthode 'addEmail'". Qu'est-ce qui me manque?

La documentation de Sequelize indique si les modèles sont User and Project, "Cela ajoutera des méthodes getUsers, setUsers, addUsers to Project, and getProjects, setProjects et addProject to User".

Cela m'amène à croire (en regardant les promesses) que je suis mal compris comment utiliser les fonctions asynchrones de Node. J'ai essayé à la fois une version synchrone et asynchrone d'insertion, tous deux renvoyant le même message ci-dessus.

Sequelize Documentation: http://docs.sequelizejs.com/en/latest/docs/associations/

Code:

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: "[email protected]" }); console.log(tEmail); res.render('index', { title: 'Express' }); }); module.exports = router; 

OU

 /* 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: "[email protected]" }).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' }); 

Comment puis-je ajouter à la table 'Individual_Email' de la meilleure façon? Je suppose que je dois le faire de manière synchrone pour attendre la mise à jour, mais je suis ouvert à toutes les suggestions. Merci!

Lorsque vous appelez .save() ou .create() ou d'autres méthodes qui renvoient une promesse, vous devez appeler .then() sur cette promesse. Lorsqu'il se résout, c'est-à-dire lorsque l'objet est sauvegardé / créé / quelque chose à faire, votre fonction sera appelée et recevra l'objet sauvegardé ou créé en tant que paramètre.

Ainsi, votre première tentative pourrait être réécrite comme suit:

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

Le code ci-dessus manque de quelques éléments importants, comme le return des promesses d'un meilleur chaînage et d'une gestion des erreurs, mais c'est un début. Je recommanderais la documentation de Bluebird sur la question (c'est la bibliothèque Promise que Sequelize utilise, mais il y en a plusieurs autres)

Vous pouvez atténuer le " Pyramid of Doom " en utilisant les promesses de la meilleure façon:

 var createdIndividual; models.Individual.create({ name: "Test" }).then(function(createdIn) { // note the argument createdIndividual = createdIn; return models.Email.create({ address: "[email protected]" }); }).then(function(createdEmail) { // note the argument return createdIndividual.addEmail(createdEmail); }).then(function(addedEmail) { // note th-- well you get the idea :) console.log("Success"); }); 

Cordialement, Nicholls

J'ai compris comment le résoudre d'une manière, mais faites-moi savoir s'il y a une meilleure façon.

Ma solution: puisque .create () a retourné une promesse, j'ai plutôt utilisé .build () qui a renvoyé une instance, et seulement ajouté à 'Individual_Email' après que les deux ont été enregistrés de manière synchrone. J'ai ensuite appelé la méthode d'ajout sur l'instance renvoyée de .build () et insérée dans la table.

Mon code:

 var tIndividual, tEmail; tIndividual = models.Individual.build({ name: "Test" }); tEmail = models.Email.build({ address: '[email protected]' }); tIndividual.save() .success(function(){ tEmail.save() .success(function(){ tIndividual.addEmail(tEmail); }); });