2

I am building a nodeJS, hapiJS and Sequelize (with PostgreSQL) application and have some issues when I'm using a for loop inside a promise chained in a transaction with Sequelize.

I would like to query my database with different content inside a contents list.

I have founded some solutions with Promises.all() or Promise.map() but I cannot apply this to my problem.

Can anyone explain me the right direction?

db.User.sequelize.transaction(function(t){
         return db.User.findOrCreate({
            where: {
                name: request.payload.user.id
            },
            transaction: t
        })
        .then( userResult => {
            return db.Order.findOrCreate({
                where: {
                    userId : userResult[0].dataValues.userId,
                    code : request.payload.order.code,
                    brand : request.payload.order.brand,
                    date : request.payload.date
                },
                transaction: t
            })
        })
        // ############## HERE ##################
        .then( orderResult => {
            console.log("I WILL BE PRINTED")
            for (var i = 0; i < request.payload.content; i++){
                console.log("I WILL NOT BE PRINTED")
                db.Product.findOrCreate({
                    where :{ean : request.payload.content[i].product.ean},
                    transaction: t  // FAIRE BOUCLE CONTENT
                })
                .then( productResult => {
                    return db.Info.findOrCreate({
                        where: {
                            //TODO : prefix et password
                            productId: productResult[0].dataValues.productId,
                            orderId: orderResult[0].dataValues.orderId
                        }
                    }).then( infoResult => {
                        console.log(productResult)
                        return db.Range.create({
                            infoId : infoResult[0].dataValues.infoId,
                            low : productResult[0].dataValues.offset,
                            high : request.payload.content[i].quantity
                        })
                    })
                })
            }
        })
        .then(res => { return console.log("ok")})
    })
  • 1
    Possible duplicate of [JavaScript ES6 promise for loop](https://stackoverflow.com/questions/40328932/javascript-es6-promise-for-loop) – Keith Apr 11 '18 at 15:20
  • If the `console.log` inside of the loop does not show up, then one problem is with the condition of the loop. But you need to solve it with `Promise.all` or `Promise.map`. Why do you think that they cannot be applied to your problem? – t.niese Apr 12 '18 at 04:52
  • @t.niese I meant that i did not succed in applying them – Boris El Gareh Apr 12 '18 at 07:35

1 Answers1

1

The thing here is that you never create a promise in the first place. Your loop doesn't return a promise at all and Promise.all fires back only when all promises are resolved.

Since you are using es6 syntax you might as well use the map method instead of a for loop. It is a more functionnal approach.

It would result in something like:

Promise.all(request.payload.content.map(content => {
    db.Product.findOrCreate({
        where :{ean : content.product.ean},
        transaction: t
    })
})

If you prefer to stick to the for loop the strategy is the same. Wrap your loop in promise.all which will store all the returned promises by your query in an array. When the loop ends and all promises are resolved, promise.all will be triggered. Note that if a single promise is rejected, promise.all will be rejected

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Alex Mass
  • 171
  • 2
  • 11
  • You call `resolve()` before the async call of `findOrCreate` is finished. And `findOrCreate` already returns a Promise, so there is no need to wrap it into another Promise. – t.niese Apr 12 '18 at 04:57
  • Thank you for the reply, it works! You should edit the line `where :{ean : request.payload.content[i].product.ean}` by `where :{ean : content.product.ean}` – Boris El Gareh Apr 12 '18 at 08:35
  • Glad it helped you! You're right I just copy pasted your loop and didn't change the core, forgot about that, thanks! – Alex Mass Apr 12 '18 at 10:21