-1

I have an application with node.js and expressjs and now I have a problem when I tried to insert several records into the database.

I have an array with 4 records and the applications insert 3 and the last one returns me a deadlock error from SQL.

I think that problem could be because of the promise inside the for a loop.

Next you have a resume of the code:

 processOrder: (req, res) => {
  //Collecting data for variables
  //Promise to wait for data
  Promise.all([data]).then(function(result)
  {
    //iterate an array
    for (var i = 0; i < result[0].length; i++)
    {
      var new_record = request.query("INSERT INTO table_test (name, local, date) VALUES ('"+result[0][i].name+"', '"+result[0][i].local+"', '"+result[0][i].date+"')");

      //Promise to wait for insert
      Promise.all([ new_record]).then(function(result)
      {
        console.log("Record number "+i+" inserted");
      }).catch(function(err) {
        console.log(err);
        console.log("Erro collecting data");
     });
    }

    console.log("END");
    res.send('true');

  }).catch(function(err) {
    console.log(err);
    console.log("Erro collecting data");
  });

}

The output is:

END
Record number 1 inserted
Record number 2 inserted
Record number 3 inserted
deadlock error

The "END" console.log should be the last log and not the first.

How can I solve this situation? Please explain to me what I'm doing wrong.

Thank you

Yaser Darzi
  • 1,480
  • 12
  • 24
user3242861
  • 1,839
  • 12
  • 48
  • 93
  • 'deadlock' is the wrong terminology for the behavior you noticed. https://stackoverflow.com/a/16530208/6129793 – Peter Oct 02 '19 at 13:34

2 Answers2

1

You are doing asynchronus stuff inside your for-loop (your query). The output of "END" is outside of the loop. You are starting 4 Promises, but you are nowhere waiting for them to resolve. So the end is printed first because the for-loop is finished as soon as the Promises are created (not really finished, but javascript contnious with the next command).

You could await the Promise inside your for loop to resolve this. Instead of

Promise.all([ new_record]).then(function(result)

you can use

const result = await new_record;

Therefore you have to mark the whole function as async

Pastafari
  • 171
  • 9
1

I rewrote your code below.

You can try.

import { request } from "http";

processOrder: (req, res) => {
//Collecting data for variables
//Promise to wait for data

Promise.all([data])
.then(function(result){
  const requests = result[0].map(record => {
      // assume request.query returns promise
      return request.query("INSERT INTO table_test (name, local, date) VALUES ('"+record.name+"', '"+record.local+"', '"+record.date+"')");
  }) 
  Promise.all(requests)
  .then(function(result){
    console.log("END");
    res.send('true');
  })
  .catch(function(err) {
    console.log(err);
    console.log("Erro collecting data");
  });  
})
.catch(function(err) {
  console.log(err);
  console.log("Erro collecting data");
});
}  

If you want to log "Record Number X inserted", then make promised function which execute request.query and console.log.

function requestPromise(queryStmt, index){
    return new Promise(resolve, reject){
        request.query(queryStmt)
        .then(result => {
           console.log(`Record Number ${index} inserted`);
           resolve(result);
        })
        .catch(err){
           reject(err);
        })   
    }
}

and then call above function like this

Promise.all([data])
.then(function(result){
   const requests = result[0].map((record, index) => {
      return requestPromise("INSERT INTO table_test (name, local, date) VALUES ('"+record.name+"', '"+record.local+"', '"+record.date+"')", index);

})

ryuken73
  • 763
  • 5
  • 13