dtburgess
dtburgess

Reputation: 613

express and sequelize - load unrelated models in same route

I have an express application where I want to load related and separate models and supply them separately to the view. I have the related bus, family and person models loading properly, but now want to also load volunteerTypes and supply that to the view as a separate object.

exports.get = (request, response) => {
  bus.findAll({include: [{model: family, include: [person]}]})
      .then(buses => buses.map(addCount))
      .then(volunteerTypes => volunteerType.findAll())
      .then((buses, volunteerTypes) => response.render('pages/register', {buses: buses, volunteerTypes: volunteerTypes}));
};

I think this should be simple, however I have not been able to determine the proper syntax for this. The sequelize docs contain lots of examples of loading related data using eager loading, but I could find an example that illustrates how to load separate models. FWIW, the output of the node console does indicate that a separate query on the volunteerType model is run. So this may just be a question of properly storing the results of this query so that it can be passed to the view.

UPDATE: addCount is simply adding a property to each bus in the buses array. I don't think it is relevant to my question, but here is the code as requested:

const atCampPeople = thisFamily => thisFamily.dataValues.people.filter(pers => pers.isAtCampPerson).length;
const countPeople = (count, thisFamily) => count + atCampPeople(thisFamily);

const addCount = thisBus => {
  thisBus.dataValues.count = thisBus.dataValues.families.reduce(countPeople, 0);
  return thisBus.dataValues;
};

Upvotes: 0

Views: 629

Answers (1)

asosnovsky
asosnovsky

Reputation: 2235

So based on what I see, I think that you lack some understanding of promises.

This part of the code:

bus.findAll({include: [{model: family, include: [person]}]})
      .then(buses => buses.map(addCount))

Returns a Promise that resolves the busses array.

While this part

volunteerType.findAll()

Resolves a Promise that resolves to the entire collection of volunteerType.

When you do this:

.then(volunteerTypes => volunteerType.findAll())

What you are really doing is busses => busses .findAll(), because the promise from before resolves the busses array. So this should return an undefined results or throw an error.

What I suggest is to load the volunteerType model and pass it into a function that can resolves two promises.

Below is the corrected code (note that I am using Promise.all to resolve two different promises at the same time, one to get the busses and mutate them, the other to grab volunteers:

exports.get = (request, response) => {
    return Promise.all([
        // Grab and mutate busses
        bus.findAll({
            include: [{
                model: family, include: [person]
            }]
        }).
        then(buses => buses.map(addCount)),
        // grab volunteerType
        volunteerType.findAll()
    ]).
    // This now returns an Array with the resolution of each promise
    then( ([busses, volunteerType]) =>  
        response.render('pages/register', {
            buses, 
            volunteerTypes
        })
    )
};

Upvotes: 1

Related Questions