Continuando com a série de JavaScript Assíncrono, dessa vez falando sobre as Callbacks: o que são, o que fazem, como funcionam? Tudo o mais será “desvendado” nesse artigo!

Callbacks: afinal, o que são?

Só para exemplificar, imagine que você está trocando bilhetes com alguém, e que vocês estão usando a mesma caneta. Se você começa escrevendo, enquanto você executa o “método” escrever, a outra pessoa está esperando você terminar. Enquanto isso, ela lê um livro. Somente quando você termina de escrever e passa o bilhete para ela, juntamente com a caneta, é que ela vai executar o método “escrever”. Do mesmo modo, você vai executar uma outra tarefa.

Essa capacidade de exercer uma outra atividade enquanto executa-se uma outra função é o princípio de uma callback!

Podemos entender melhor o que é uma Callback – ou, mais comumente, uma função Callback – ao traduzir o seu nome, que significa “chamar de volta”. Com isso já temos uma ideia de que é algo que eventualmente será chamado novamente.

Além disso, Callbacks são funções que recebem outras funções como parâmetro. Um bom exemplo é o uso do forEach, que é um método do objeto Array. Lembrando que métodos são funções, só que no escopo dos objetos

Por exemplo:

const frutas = ['Maçã', 'Banana', 'Melancia']

function listaCompras(nome, indice) {
    console.log(`${indice + 1} - ${nome}`)
}
frutas.forEach(listaCompras)
//A impressão é:
//1 - Maçã
//2 - Banana
//3 – Melancia

O forEach é um ótimo exemplo porque é um método que recebe e aplica uma determinada função em cima de um Array. No exemplo acima, a função listaCompras está imprimindo somente o índice dos valores armazenados no Array e o nome da fruta correspondente.

Como o forEach já recebe uma função como parâmetro, não é necessário passar os parênteses da função, pois ela já é reconhecida como tal.

Callbacks em URL

O exemplo anterior foi de uma Callback relacionada a uma função, mas podemos usar as Callbacks quando relacionadas a um evento de um browser, como o clique de um mouse.

É possível disparar uma função Callback quando um evento onclick disparar no browser, como por exemplo:

<!DOCTYPE html>
<html>

<head>
    <meta charset='UTF-8'>
    <title>Trabalhando com Eventos #01</title>
</head>

<body class="conteudo exercicio">
    <div>
        <!-- onclick="navegarEm5s(event)" -->
        <a espera-um-pouco href="https://google.com.br">Google</a>
    </div>
    <script>
        function navegarEm5s(e) {
            e.preventDefault()
            console.log('Saindo em 5s...')
            setTimeout(() => {
                const link = e.target
                window.location.href = link.href
            }, 5000)
        }

        // const a = document.querySelector('a')
        // a.onclick = navegarEm5s

        const a = document.querySelector('[espera-um-pouco]')
        a.onclick = navegarEm5s
    </script>
</body>

No código acima, o evento onclick vai disparar a chamada da função navegarEm5s, que vai contar até 5 antes de finalmente chamar a página do Google. Essa passada da função, atrelada a um evento, é como usamos Callbacks atreladas a URLs. Podemos dizer também que os EventHandlers são um tipo de callback!

Utilidade das funções callback

Usamos as funções Callback especialmente no desenvolvimento Web, como por exemplo na execução de efeitos visuais. Podemos usá-las em outros casos, tais como:

  • Programação assíncrona;
  • Event Listeners;
  • Métodos diversos, como o setTimeout, setInterval, map, filter e forEach;
  • Criação de APIs.

Métodos que usam funções Callback

Como mencionado anteriormente, além do método forEach, os métodos map, filter, setTimeout e setInterval usam os conceitos de callback.

Método forEach

O método forEach recebe uma função aplicada aos elementos do Array informado ao forEach, conforme é percorrido.

const frutas = ['Maçã', 'Banana', 'Melancia']

function listaCompras(nome, indice) {
    console.log(`${indice + 1} - ${nome}`)
}
frutas.forEach(listaCompras)

Método map()

Assim como o forEach, o map também aplica uma determinada função em todos os índices do Array que passou-se para ele. Porém, diferente do forEach, o map vai retornar um novo Array com os novos valores como resultado. Por exemplo:

const nums = [1, 2, 3, 4, 5]

let resultado = nums.map(function(valor) {
    return valor * 2
})

console.log(resultado) //retorna o novo Array [ 2, 4, 6, 8, 10 ]

Método filter()

O método filter() também vai aplicar aos valores de um Array passado para ele uma determinada função, e vai retornar os valores que cumprirem a condição especificada por essa função.

Por exemplo, vamos supor que queremos separar os produtos cujo preço é maior do que 500 e que são frágeis. Um jeito de fazer seria o seguinte:

const produtos = [
    {Nome:"Notebook", preco: 2499, fragil: true},
    {Nome:'iPad Pro', preco: 4199, fragil: true},
    {Nome:'Copo de Vidro', preco: 12.19, fragil: true},
    {Nome:'Copo de Plástico', preco: 18.99, fragil: false}
]

console.log(produtos.filter(function(p){
     if (p.preco > 2000 && p.fragil == true) {
        return p 
    }
})) 
//O resultado é:
//{ Nome: 'Notebook', preco: 2499, fragil: true },
//{ Nome: 'iPad Pro', preco: 4199, fragil: true }

Método setTimeout()

O método setTimeout vai executar uma determinada função depois de uma determinada quantidade de tempo. Usamos esse método no artigo sobre Promises para exemplificar a programação assíncrona. Funciona da seguinte forma:

console.log("Essa é impressa imediatamente...")

let teste = setTimeout(function() {
    console.log("...E essa é impressa depois de 5 segundos.");
  }, 5000)

É importante ressaltar que o tempo passado para o método não é o tempo garantido de execução, e sim o tempo mínimo de execução.

Método setInterval()

O setInterval, assim como o setTimeout, também executa uma função com um determinado período, mas esse método executa a mesma função a cada intervalo de tempo. Da seguinte forma:

console.log("Essa é impressa imediatamente...")

let teste = setInterval(function() {
    console.log("...E essa é impressa depois de 2 segundos.");
  }, 2000)

A segunda String vai ser impressa a cada dois segundos, repetidamente.

Conclusão

E esse foi o segundo artigo referente ao funcionamento do JavaScript Assincrono! No próximo artigo dessa sequência vamos aprender sobre Async/Await.

Até a próxima e bons estudos!