Testing that all asynchronous functions have been terminated

Asked

Viewed 61 times

1

Greetings
I’m developing a synchronizer between two databases (SQL Server and MySQL) with the ElectronJS and the Node.JS and everything is working fine, but I would like it to perform synchronization of all tables (which are done asynchronously within a loop for) he executed the method window.close() to close the application.

// Removi os tratamentos de erro e conexão com o banco, porque estão funcionando

// Leio um arquivo .json que possui todas as tabelas com as colunas que eu desejo
fs.readFile(ABSPATH + 'tables.json', 'utf8', async (err,json) => {
  // Converte o conteúdo do arquivo pra um objeto JSON
  let vetor = JSON.parse(json)
  // Para cada tabela
  for (let i = 0; i < vetor.length; i++) {
    // Lê a tabela no SQL Server e salva os dados no MySQL
    await read(vetor[i].table,vetor[i].keys)
  }
  // Ao invés de fechar, estou só exibindo na tela essa mensagem (pra debug)
  document.body.innerHTML += "<h2>Todos os dados foram inseridos</h2>"
})

But, as you can see, it is returning the final result before returning the functions, that is, they remain asynchronous:
inserir a descrição da imagem aqui
I believe my mistake is at the time of saving the data, in the following function, because I tested it with the console.log(), but still, I can’t make it synchronous:

con.connect(async err => {
  // Começo a Transaction
  await con.beginTransaction(async err => {
    // Limpo a tabela
    await con.query(`TRUNCATE TABLE ${table}`, err => {})
    // Loop pra inserir todos os dados na tabela
    for (let i = 0; i < values.length; i++){
      // Crio e executo um insert
      await con.query(createInsert(table,keys,values[0]), err => {})
    }
    // Encerro a Transaction quando está tudo inserido
    await con.commit(err => {
        // Escrevo na tela que os dados foram salvos
        document.body.innerHTML += `<p>Dados de ${table} cadastrados com sucesso.</p>`
    })
  })
  // Fim da Transaction
})

1 answer

2


Nary, the operator await makes your code wait for the resolution of a Promise, it does not make your code synchronous. To use await, these functions need to return a promise, which I’m not sure is the case with your code, and besides, it makes no sense to use callbacks, when you are already using await.

If your object does not return files, you can create new methods. There are other approaches to this problem, but this is a suggestion:

Object.defineProperty(con.__proto__, {
  asyncConnect: {
    configurable: true,
    value() {
      return new Promise((resolve, reject) => this.connect(err => err ? reject(err) : resolve()))
    }
  },

  asyncBeginTransaction: {
    configurable: true,
    value() {
      return new Promise((resolve, reject) => this.beginTransaction(err => err ? reject(err) : resolve()))
    }
  },

  asyncQuery: {
    configurable: true,
    value(arg) {
      return new Promise((resolve, reject) => this.query(arg, err => err ? reject(err) : resolve()))
    }
  },

  asyncCommit: {
    configurable: true,
    value() {
      return new Promise((resolve, reject) => this.commit(err => err ? reject(err) : resolve()))
    }
  }
});

Now with these methods you can use the operator await. Note that I no longer use callbacks.

await con.asyncConnect()
// Começo a Transaction
await con.asyncBeginTransaction()
// Limpo a tabela
await con.asyncQuery(`TRUNCATE TABLE ${table}`)
// Loop pra inserir todos os dados na tabela
for (let i = 0; i < values.length; i++) {
  // Crio e executo um insert
  await con.asyncQuery(createInsert(table, keys, values[i]))
}
// Encerro a Transaction quando está tudo inserido
await con.asyncCommit()
// Escrevo na tela que os dados foram salvos
document.body.innerHTML += `<p>Dados de ${table} cadastrados com sucesso.</p>`

Of course, this code is just an adapted version of what you posted. It is still necessary to make some improvements like error handling and move this logic to the back end.

  • Thank you, it worked as expected (at least this problem).

Browser other questions tagged

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