0

I'm using Sequelize and PostgreSQL in my node.js application. I have two tables with one-to-one relationship - Customers and Users.

There is foreign key UserId in the Customers table. So, I firstly insert into the Users table and then insert into the Customers with the last inserted UserId. Here is my controller code:

var self = this;

async.each(data, function(row, callback) {
    var userData = {
        name: row.name,
        /** **/
    }
    // self.User is User model
    self.User.create(userData).then(function(user) {
      console.log("[User.create] succeeded");
      /** **/
      // self.Model is Customer model
      self.Model.create(cusData).then(function(customer) {
          console.log("[Customer.create] succeeded");
          /** **/
      }).catch(function(err) {
          throw err;
      }); // EOL self.Model.create
    }).catch(function(err) {
          throw err;
    }); // EOL self.User.create
    callback();
}, function(err){
    if (err) {
        throw err;
    }
}

I'm using async.each() to loop the array of 2 records synchronously. When I inserted the two records, the console output is:

[User.create] succeeded
[User.create] succeeded
[Customer.create] succeeded
[Customer.create] succeeded

What I expected is:

[User.create] succeeded
[Customer.create] succeeded
[User.create] succeeded    
[Customer.create] succeeded

I think it could be a problem of synchronous flow in asynchronous programming. What am I wrong? I think I'm using the callbacks correctly.

3
  • How did you insert two records? You might be calling that twice in sequence, which starts two inserts before the callbacks have the opportunity to fire. If you want the full inserts done in sequence, you need to begin the second one in the first's last callback. Commented Dec 20, 2014 at 13:25
  • @DenisdeBernardy Ah...I use a node module Async.js to loop the records. I updated the code in my question. Commented Dec 20, 2014 at 13:34
  • @DenisdeBernardy likely to be the mis-placed call of callback()? Commented Dec 20, 2014 at 13:35

1 Answer 1

1

You're initiating the two inserts asynchronously, so you've no guarantee on the order of the follow-up queries. For all you know, depending on locks, you could get the current or your expected result.

To force the order, move the iteration forward from within the inner callback:

  self.Model.create(cusData).then(function(customer) {
      console.log("[Customer.create] succeeded");
      /** move the iterator forward here, using e.g. recursion **/
  })
Sign up to request clarification or add additional context in comments.

4 Comments

The iterator forward means callback()?
No, I mean that you need to use a proper iterator or something that amounts to one, which can yield as needed, or locks as needed, or be advanced step by step, e.g. iter = function(cb, arr, idx) { cb(arr, idx); /* which takes care of calling iter(arr, idx + 1); */ }; or whatever is that is more appropriate and actually valid. Your current code basically contains a logic error if you wish to force the order.
Alternatively, don't use the each.async method, plain and simple, and reorganize your code accordingly.
async.whilst() did solve my problem. Thank you. don't know why async.each() not work.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.