Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

connection.end() e função assíncrona do NodeJS

Perdi um bom tempo tentando entender o que estava dando errado no meu código e percebi que dessa forma:

pagamentos.js

            if(pagamento.forma_de_pagamento == "cartao"){
                const cartao = req.body["cartao"];    
                const serviceCartoes = new app.servicos.cartoesClient();
                serviceCartoes.autoriza(cartao, (exception, request, response, data) => {
                    if(exception) {
                        console.log(exception);
                        resp.status(400).send(exception);
                        return;
                    }
                    const res = {
                        dados_de_pagamento : pagamento,
                        cartao : data,
                        links : [
                            {
                                href : "http://localhost:3000/pagamentos/pagamento/"+pagamento.id,
                                rel : PAGAMENTO_CONFIRMADO,
                                method : "PUT"
                            },
                            {
                                href : "http://localhost:3000/pagamentos/pagamento/"+pagamento.id,
                                rel : PAGAMENTO_CANCELADO,
                                method : "DELETE" 
                            }
                        ]
                    };
                    resp.location("/pagamentos/pagamento/"+ pagamento.id);
                    resp.status(201).json(res);
                });
                return;
            }

Consigo fazer funcionar, porém eu deixo a conexão do banco aberta.

Porém quando eu coloco o connection.end(), ele me retorna um erro:

            if(pagamento.forma_de_pagamento == "cartao"){
                const cartao = req.body["cartao"];    
                const serviceCartoes = new app.servicos.cartoesClient();
                serviceCartoes.autoriza(cartao, (exception, request, response, data) => {
                    if(exception) {
                        console.log(exception);
                        resp.status(400).send(exception);
                        return;
                    }
                    const res = {
                        dados_de_pagamento : pagamento,
                        cartao : data,
                        links : [
                            {
                                href : "http://localhost:3000/pagamentos/pagamento/"+pagamento.id,
                                rel : PAGAMENTO_CONFIRMADO,
                                method : "PUT"
                            },
                            {
                                href : "http://localhost:3000/pagamentos/pagamento/"+pagamento.id,
                                rel : PAGAMENTO_CANCELADO,
                                method : "DELETE" 
                            }
                        ]
                    };
                    resp.location("/pagamentos/pagamento/"+ pagamento.id);
                    resp.status(201).json(res);
                });
        connection.end();
                return;
            }
Consumindo API cartoes/autoriza events.js:183 throw er; // Unhandled 'error' event ^

Error: Cannot enqueue Quit after invoking quit.

Eu imagino que tenha alguma coisa á ver com o callback assíncrono do NodeJS. Porém eu não entendi direito como funciona essa função assíncrona. Só vai executar o callback quando a API externa retornar o cartão? E por isso da erro por que ele segue para o próximo statement que é connection.end()?

3 respostas
solução!

Isso Leonardo, como o callback que salva os dados no banco vai ser executado posteriormente, o node passa para o próxima linha que encerra a execução, então você acaba com o erro por que o callback pode não ter finalizado ainda antes da conexão ser fechada.

Você pode encadear o .end logo ao fechar do parêntese do .query, mas como você postou o código incompleto, eu fiquei sem saber de fato onde o query estava pra tentar te mostrar o que poderia fazer.

PagamentoDAO.js

function PagamentoDAO(connection){
    this._connection = connection;

    PagamentoDAO.prototype.salva = (pagamento, callback) => {
        this._connection.query("INSERT INTO pagamento SET ?", pagamento, callback);
    };

    PagamentoDAO.prototype.lista = callback => {
        this._connection.query("SELECT * FROM pagamento", callback);
    };

    PagamentoDAO.prototype.buscaPorId = (id, callback) => {
        this._connection.query("SELECT * FROM pagamento WHERE id =",[id], callback);
    };

    PagamentoDAO.prototype.atualiza = (pagamento, callback) => {
        this._connection.query("UPDATE pagamento SET status = ? WHERE id = ?", [pagamento.status, pagamento.id], callback);
    };
}

module.exports = () => {
    return PagamentoDAO;
};

Se eu encadear um .end() no final de cada query dessa, ele vai executar primeiro a função query() e depois executar a função .end() mesmo que a primeira executa uma função de callback?

Se não estou enganado sim.