How to expect the answer of an asynchronous function (Javascript/Cordova)?

Asked

Viewed 175 times

0

I am developing a Cordova app and I am using the Sqlite plugin to make queries in the database. But as the functions of querys are asynchronous I have a problem to create a multidimensional array.

tx.executeSql("select que pesquisa os grupos", [], function(tx, grupos) {

    var arrayGrupos = []; // Cria uma variavel para armazenar os grupos
    for(grupoAtual in grupos) { // faz o loop pelos grupos

        var arrayItensGrupos = []; // Cria uma variavel para armazenar os itens dos grupos
        tx.executeSql("select que pesquisa os itens dos grupos", [], function(tx, itensGrupos) {

            for(itemAtual in itensGrupos) { // faz o loop pelos itens dos grupos

                detalhesItem = { // Cria o item
                    nomeItem: itemAtual.nome_item
                    ...
                }
                arrayItensGrupos.push(detalhesItem); // Adiciona o item ao array

            }

        }

        detalhesGrupo = { // Cria o grupo
            nomeGrupo: grupoAtual.nome_grupo,
            listadeItens: arrayItensGrupos //** adiciona o array com os itens
        }
        arrayGrupos.push(detalhesGrupo); // Adiciona o grupo ao array

    }

});

When I give a console.log in the group array (arrayGrupos) it returns the groups with the right name, but the array with the list of items of the group (listadeItens: arrayItensGrupos) empty. Some groups have several items and others do not, in those with few items comes the normal list but in the group that takes a little longer it does not expect to return all items (by the function being asynchronous) and shows as if the list is empty.

So you can wait for the function executeSql(asynchronous) return the result to proceed?

1 answer

1

How comfortable are you with Javascript? Use to wait for the answer Promise. This makes it even easier to optimize the query, because you can use Promise class methods to perform multiple queries asynchronously, without one having to wait for the answer of the other, as would be the ideal in your loop for.

For the question, I suggest the solution below. if you are not yet familiar with Promises, async and await, please read the documentation or ask a new question.

// Transformo o método numa função que retorna Promises
const executeSQL = (query, arr) => new Promise(resolve => tx.executeSQL(query, arr, (tx, grupo) => resolve(grupo)))

// Faço a query dos grupos utilizando await
var grupos = await executeSql("select que pesquisa os grupos", [])
// Faço todas as queries dos itens simultaneamente, e espero por elas finalizarem
var itensGrupos = await Promise.all(grupos.map(grupoAtual => executeSql("select que pesquisa os itens dos grupos", [])))

// Monto o array
var arrayGrupos = grupos.map((grupo, i) => ({
    nomeGrupo: grupo.nome_grupo,
    listadeItens: itensGrupos[i].map(item => ({
        nomeItem: item.nome_item
        // ...
    }))
}))
  • I confess that as much as I have advanced and enough in javascript I do not know why I could not learn Promise's, I’ve read the documentation but I found it kind of confusing I don’t know, I’ll test your answer that is looking pretty simple to implement in my other functions.

Browser other questions tagged

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