Conheça o Callback Hell
JavaScript assíncrono, ou JavaScript que usa callbacks, é complicado de acertar intuitivamente. A causa do call-back hell é quando as pessoas escrevem JavaScript de uma maneira que ocorre a execução de cima para baixo, visualmente falando. Em algumas outras linguagens, como C, Python, existe a expectativa de que o que quer que aconteça na linha 1, tenha que terminar antes que o código da linha 2 execute, e assim por diante. Mas no JavaScript, isso funciona de uma maneira diferente.
O que são Callbacks?
São apenas o nome de uma convenção para o uso de funções JavaScript. Não existe nada chamado “callback” no JavaScript, sendo apenas uma convenção. Em vez de utilizar retorno imediato como a maioria das funções. As funções call-back demoram algum tempo para produzir resultados. A palavra “assincronismo”, conhecida no JavaScript como “async”, significa “demora algum tempo / acontece no futuro”.
Quando você chama uma função normal, pode usar seu valor de retorno:
let resultado = multiplicarDoisNumeros(5, 10); console.log(resultado);
No entanto, funções assíncronas e que usam call-backs não retornam nada imediatamente:
let foto = downloadFoto('http://coolcats.com/cat.gif') // foto é 'undefined'!
Nesse caso, o gif pode demorar muito para ser baixado e você não deseja que seu programa seja pausado enquanto aguarda a conclusão do download. Em vez disso, você armazena o código que deve ser executado logo após a conclusão do download em uma função. Este é o callback. Você executa a função downloadFoto e ele executará seu callback, quando o download estiver concluído e passará a foto (ou um erro se algo der errado).
downloadFoto('http://coolcats.com/cat.gif', lidarComFoto) function lidarComFoto (error, foto) { if (error) console.error('Erro de Download!', error) else console.log('Download finished', foto) } console.log('Download iniciado')
Como podemos evitar o callback hell?
-
Mantenha seu código limpo:
Callback hell geralmente é causado por más práticas de codificação. Escreva melhor o seu código e não passará trabalho.
let form = document.querySelector('form'); form.onsubmit = function formSubmit (submitEvent) { let name = document.querySelector('input').value; request({ uri: "http://example.com/upload", body: name, method: "POST" }, function postResponse (err, response, body) { let statusMessage = document.querySelector('.status'); if (err) return statusMessage.value = err; statusMessage.value = body; }) }
Nomear funções é uma prática benéfica e facilita a leitura do código.
Agora podemos mover as funções para o nível superior do nosso programa:
document.querySelector('form').onsubmit = formSubmit; function formSubmit (submitEvent) { let name = document.querySelector('input').value; request({ uri: "http://example.com/upload", body: name, method: "POST" }, postResponse) } function postResponse (err, response, body) { let statusMessage = document.querySelector('.status'); if (err) return statusMessage.value = err; statusMessage.value = body }
-
Modularize:
Segundo Isaac Schlueter (do projeto Node.js): “Escreva pequenos módulos que cada um faz uma coisa e monte-os em outros módulos que fazem uma coisa maior. Você não terá um callback hell se não for lá”.
Criando um módulo, ficaria assim:
module.exports.submit = formSubmit function formSubmit (submitEvent) { let name = document.querySelector('input').value; request({ uri: "http://example.com/upload", body: name, method: "POST" }, postResponse) } function postResponse (err, response, body) { let statusMessage = document.querySelector('.status'); if (err) return statusMessage.value = err; statusMessage.value = body; }
-
Lide com todos os erros:
Existem diferentes tipos de erros: de sintaxe, de runtime, erro de permissões, falha no disco rígido, entre outros. Ao lidar com callbacks, você, por definição, está lidando com tarefas despachadas, executa algo em segundo plano e, em seguida, conclui com êxito ou aborta devido a alguma falha. Podemos manipular isso deixando o primeiro argumento da função callback reservada ao erro.
function lidarComFoto (error, foto) { if (error) console.error('Erro de Download!', error) else console.log('Download finished', foto) }
Dito isto, sempre lide com todos os erros e mantenha seu código simples e limpo.
Para maiores informações, acesse o site: http://callbackhell.com/
Referências: http://callbackhell.com/