Minoru
Minoru

Reputation: 1730

Wait for queries with sequelize

I'm currently using Node.js with Sequelize (MySQL) and have two models that have an association between them: M.belongsTo(C). What I'm trying to do is to query all C and add all M that belongs to C to the returned JSON object. See code below that represents my latest attempt:

C.findAll({
    where: {
        parent_ids: ids
    }
}).then(cs => {
    let fCs = [];
    for (let j = 0; j < cs.length; j++) {
        let c = cs[j].get({ plain: true });

        M.findAll({
            where: {
                CId: c._id
            }
        }).then(ms => {
            let cMs = [];
            for (let k = 0; k < ms.length; k++) {
                cMs.push(ms[k].get({ plain: true }));
            }

            c.ms = cMs;
        });

        fCs.push(c);
    }

    return res.json({
        success: true,
        cs: fCs
    });
}).catch(error => {
    return res.json({
        success: false
    });
});

The problem is that the inner query on M model is made as an async query and I get the response before any query is performed. I tried also using Promise.all(), but I couldn't make it work properly because I'm iterating in the outer C query.

How can I make it work as expected?

Upvotes: 3

Views: 3806

Answers (1)

Raj Kumar N
Raj Kumar N

Reputation: 793

Since db queries are async actions the loop completes without any query being executed, so to prevent this push all findAll calls to an array and Promise.all(arrayOfPromises) will resolve those promises once all findAll promises are successfully resolved.

var fCs = [], cs,
C.findAll({
  where: {
    parent_ids: ids
  }
}).then(data => {
  cs = data;
  var promises = [];
  for (let j = 0; j < cs.length; j++) {
    let c = cs[j].get({ plain: true });

    promises.push(M.findAll({
        where: {
            CId: c._id
        }
    }).then(ms => {
        let cMs = [];
        for (let k = 0; k < ms.length; k++) {
            cMs.push(ms[k].get({ plain: true }));
        }

        return cMs;
    }));
  }
  return Promise.all(promises)
}).then(result => {
  fcs = cs.map((el, index) => {
    let obj = el.get({plain:  true})
    obj.ms = result[index]
    return obj
  })
  return res.json({
    success: true,
    cs: fCs
  });
}).catch(error => {
  return res.json({
    success: false
  });
});

Upvotes: 4

Related Questions