Data synchronization, mysql and Promise

Asked

Viewed 132 times

0

I’m a beginner in Node.js and I’m trying to understand why I can’t bring the expected result of my API.

I have an application that sends an array of data to an API on Node to be saved to the database. When I receive this data I need to check if each of them is saved in my database db.buscaPorId(). If each record is not saved, a function db.salva() saves each of these new records at the bank. At the end of this process I would like to return all data (new and old) to my application.

The problem is at the time of giving a GET on all records after foreach, as it does not return the last data that has just been saved. Only those who were previously saved...

What I tried is in the code below.

What would be the best way to solve this? I’m studying Precedents but I still can’t quite understand how to put it into practice in my code. Note: the code is probably full of flaws, so if someone can give me a tip to improve it would be nice :)

Function of the route

sincroniza(app) {
    return function (req, res) {
        const dadosApp = req.body;

        const conexao = app.persistencia.ConexaoDb();
        const db = new app.persistencia.PontoDao(conexao);

        if(dadosApp !== ""){
            console.log('recebendo dados');
            dadosApp.forEach(dado =>{
                db.buscaPorId(dado.uuid,(erro,resultado)=>{
                    if(resultado == '' || resultado == undefined || resultado.length == 0){
                        dado.sync = 1;
                        db.salva(dado,(erro,res)=>{
                            if(erro){
                                res.send('falha ao salvar os dados')
                            }
                        })
                    }
                })
            })
        }

        //não retorna os últimos dados salvos
        db.lista((erro,result)=>{                
            res.json(result);
        })

}

comics functions

function PontoDao(conn){
    this._conn = conn;

}

PontoDao.prototype.salva = function(ponto,callback){
    this._conn.query('INSERT INTO ponto SET ?', ponto, callback);
}

PontoDao.prototype.atualiza = function(ponto,callback) {
    this._conn.query('UPDATE ponto SET sync = ? where id = ?', [ponto.sync, ponto.id], callback);
}

PontoDao.prototype.lista = function(callback) {
    this._conn.query('SELECT * from ponto',callback);
}

PontoDao.prototype.buscaPorId = function (id,callback) {
    this._conn.query("select * from ponto where uuid = ?",[id],callback);
}

module.exports = function(){
    return PontoDao;
};

1 answer

1


This is a typical case of a loop forEach asynchronous code running. I talked about this here, here and here. I recommend giving a reading to better understand the problem.

In your case you can use Promise.all to wait for those requests and then run the db.lista within the .then from Promise.all. Notice that Promise.all only runs after all loop elements .map in this case they have run.

For this I suggest you change the listPorId method to work with Promises.

Example:

// muda "buscaPorId" para:
PontoDao.prototype.buscaPorId = function(id) {
  return new Promise(function(resolve, reject) {
    this._conn.query("select * from ponto where uuid = ?", [id], function(err, data) {
      if (err) reject(err);
      else resolve(data);
    });
  });
}

PontoDao.prototype.salva = function(ponto) {
  return new Promise(function(resolve, reject) {
    this._conn.query('INSERT INTO ponto SET ?', ponto, function(err, data) {
      if (err) reject(err);
      else resolve(data);
    });
  });
}


sincroniza(app) {
  return function(req, res) {
    const dadosApp = req.body;

    const conexao = app.persistencia.ConexaoDb();
    const db = new app.persistencia.PontoDao(conexao);

    let preSaving = [Promise.resolve()];
    if (dadosApp !== "") {
      console.log('recebendo dados');
      preSaving = dadosApp.map(dado => {
        return db.buscaPorId(dado.uuid).then(function(resultado) {
          if (!resultado || resultado.length == 0) {
            return db.salva(dado).catch(function() {
              res.send('falha ao salvar os dados')
            });
          }
        })
      });
    }
    //não retorna os últimos dados salvos
    Promise.all(preSaving).then(function() {
      db.lista((erro, result) => {
        res.json(result);
      })
    });
  }
}

  • Very good your answer, @Sergio . I figured I could settle with Promise, so I put it in the title. Now I have a starting point to study better and finish my code. Something I’m trying to understand is what this line does exactly? Let preSaving = [Promise.resolve()];

  • @dmgGeronimo case the if (dadosApp !== "") { is not true then the Promise.all (that accepts an array) will consume an empty and solved Pormise with [Promise.resolve()];. Makes sense?

Browser other questions tagged

You are not signed in. Login or sign up in order to post.