Entendendo sobre Callback Hell em JavaScript
Tags: javascript, programming, braziliandevs
Published: 2023-01-04 10:31:01

JavaScript assíncrono, ou JavaScript que usa callbacks, é complicado de acertar intuitivamente. A causa do callback 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:

```jsx
let resultado = multiplicarDoisNumeros(5, 10);

console.log(resultado);
```

No entanto, funções assíncronas e que usam call-backs não retornam nada imediatamente:

```jsx
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).

```jsx
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?

### 1. 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.

```jsx
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:

```jsx
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
}
```

### 2. 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ám um callback hell se não for lá"._

Criando um módulo, ficaria assim:

```jsx
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;
}
```

### 3. Lide com todos os erros

Existem diferentes tipos de erros: sintaxe, de runtime, erro de permissões, falha no disco rígido, entre outros. Ao lidar com ballbacks, 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.

```jsx
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.

## Obrigado por ler!

Espero que este artigo tenha ajudado você a entender sobre callback hell.