2016-10-08 13 views
3

Ich baue eine Website mit Node.js und Sequelize (mit einem Postgres-Backend). Ich habe eine Abfrage, die viele Objekte mit einem Fremdschlüssel zurückgibt, und ich möchte eine Liste der Objekte, die der Fremdschlüssel verweist, an die Ansicht übergeben.Sequelize-Abfragen synchron ausführen

Im Beispiel enthält Attendances Hackathon-Schlüssel, und ich möchte eine Liste von Hackathons zurückgeben. Da der Code async ist, wird die folgende Sache natürlich nicht in Knoten arbeiten:

models.Attendance.findAll({ 
    where: { 
     UserId: req.user.id 
    } 
}).then(function (data) { 
    var hacks = []; 
    for (var d in data) { 
     models.Hackathon.findOne({ 
      where: { 
       id: data[d].id 
      } 
     }).then(function (data1) { 
      hacks.append(data1); 
     }); 
    } 
    res.render('dashboard/index.ejs', {title: 'My Hackathons', user: req.user, hacks: hacks}); 
}); 

Gibt es eine Möglichkeit, dass die Abfrage in einer synchronen Art und Weise zu tun, was bedeutet, dass ich bis ich das nicht über die Ansicht zurückkehren "Hacks" Liste mit allen Objekten gefüllt?

Danke!

+0

Haben Sie Asynchron-Modul mit Wasserfall versuchen? das kann dir helfen – abdulbarik

+0

Einen Datensatz in einer Schleife zu finden, ist ein schreckliches Design. Es sollte nur eine Abfrage sein. –

Antwort

3

Verwenden Sie Promise.all, um alle Ihre Abfragen auszuführen, rufen Sie dann die nächste Funktion auf.

models.Attendance.findAll({ 
 
    where: { 
 
     UserId: req.user.id 
 
    } 
 
}).then(function (data) { 
 
    // get an array of the data keys, (not sure if you need to do this) 
 
    // it is unclear whether data is an object of users or an array. I assume 
 
    // it's an object as you used a `for in` loop 
 
    const keys = Object.keys(data) 
 
    // map the data keys to [Promise(query), Promise(query), {...}] 
 
    const hacks = keys.map((d) => { 
 
     return models.Hackathon.findOne({ 
 
     where: { 
 
      id: data[d].id 
 
     } 
 
     }) 
 
    }) 
 
    // user Promise.all to resolve all of the promises asynchronously 
 
    Promise.all(hacks) 
 
     // this will be called once all promises have resolved so 
 
     // you can modify your data. it will be an array of the returned values 
 
     .then((users) => { 
 
     const [user1, user2, {...}] = users 
 
     res.render('dashboard/index.ejs', { 
 
      title: 'My Hackathons', 
 
      user: req.user, 
 
      hacks: users 
 
     }); 
 
     }) 
 
});

1

Sie das Rad neu erfinden, hat die Sequelize Bibliothek bereits das alles durchdacht. Du hast erwähnt, dass du bereits die Fremdschlüssel eingerichtet hast, mehr als die Hälfte der Schlacht abgeschlossen.

Verwendung umfasst in Ihrer Where-Anweisung, um das Hackathons-Modell, alles in einem Aufruf zu bringen. Wenn Ihre Umgebung korrekt eingerichtet ist, funktioniert dies. Nehmen Sie sich Zeit, um die Dinge in der Bibliothek richtig einzurichten, Sie werden viel Zeit sparen, indem Sie den Fehler reduzieren und es anderen ermöglichen, sich dort wiederzufinden, wo Sie aufgehört haben, wenn es sein muss.

Sehen Sie, wie viel sauberer ist dies ...

models.Attendance.findAll({ 
    include: [{ 
     model: Hackathon, 
     as: 'hackathon' 
    }, 
    where: { 
     UserId: parseInt(req.user.id) // <---- like to parseInt to prevent SQL injection, but I believe Sequelize already covers this, can never be too safe ;-) 
    } 
}).then(function (data) { 
    // hackathon id 
    console.log(data.hackathon.id) 

    // attendance id 
    console.log(data.id) 
}) 

Weitere Infos zu Sequelize umfasst hier: http://docs.sequelizejs.com/en/latest/docs/models-usage/

+0

Sie können buchstäblich zu sicher sein. Wenn Sie nur alles in einen Aufruf von parseInt() einbetten, weil "vielleicht", dann sind Sie Frachtkult. – theraccoonbear