Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using loops and promises in transactions in Sequelize

I am currently building a Nodejs, Express, Sequelize (w. PostgreSQL) app, and have run into a few problems with using promises together with transactions and loops.

I am trying to figure out how to use a for loops in a transaction. I am trying to loop through a list of members and create a new user in the database for each of them.

I know the following code is wrong but it shows what I am trying to do.

Can anyone point me in the right direction?

        var members = req.body.members;
        models.sequelize.transaction(function (t) {
            for (var i = 0; i < members.length; i++) {
                return models.User.create({'firstname':members[i], 'email':members[i], 'pending':true}, {transaction: t}).then(function(user) {
                    return user.addInvitations([group], {transaction: t}).then(function(){}).catch(function(err){return next(err);});
                })
            };
        }).then(function (result) {
            console.log("YAY");
        }).catch(function (err) {
            console.log("NO!!!");
            return next(err);
        });
like image 891
ReturnToZero Avatar asked Feb 29 '16 17:02

ReturnToZero


People also ask

Does Sequelize return promise?

Most of the methods provided by Sequelize are asynchronous and therefore return Promises. They are all Promises , so you can use the Promise API (for example, using then , catch , finally ) out of the box.

Is Sequelize a promise?

Sequelize is an easy-to-use and promise-based Node. js ORM tool for Postgres, MySQL, MariaDB, SQLite, DB2, Microsoft SQL Server, and Snowflake. It features solid transaction support, relations, eager and lazy loading, read replication and more.

What is ORM in Sequelize?

Sequelize is a Node. js-based Object Relational Mapper that makes it easy to work with MySQL, MariaDB, SQLite, PostgreSQL databases, and more. An Object Relational Mapper performs functions like handling database records by representing the data as objects.


1 Answers

You should use a Promise.all

    var members = req.body.members;
    models.sequelize.transaction(function (t) {
        var promises = []
        for (var i = 0; i < members.length; i++) {
            var newPromise = models.User.create({'firstname':members[i], 'email':members[i], 'pending':true}, {transaction: t});
           promises.push(newPromise);
        };
        return Promise.all(promises).then(function(users) {
            var userPromises = [];
            for (var i = 0; i < users.length; i++) {
                userPromises.push(users[i].addInvitations([group], {transaction: t});
            }
            return Promise.all(userPromises);
        });
    }).then(function (result) {
        console.log("YAY");
    }).catch(function (err) {
        console.log("NO!!!");
        return next(err);
    });

I don't believe you need to catch within sequelize transactions as I think it jumps out to the catch on the transaction

Sorry for formatting. On mobile.

Promise.all will wait for all promises to return (or fail) before running the .then, and the .then callback will be all the promise data from each array

like image 134
Datsik Avatar answered Sep 20 '22 19:09

Datsik