As funções callback são funções passadas como argumentos para outras funções. A função de callback pode então ser invocada para disparar uma ação subsequente. Muitas vezes, os callbacks são usados para lidar com os resultados de um trabalho realizado, ou para lidar com uma ação quando um evento acontece. As funções callback podem ser usadas tanto na programação síncrona quanto na assíncrona.
const sideLength = 5;
// Caller function takes a callback function
function applySideLength(callback) {
return callback(sideLength);
}
// Callback must expect the possible argument from the calling function
function areaOfSquare(side) {
return side * side;
}
applySideLength(areaOfSquare); // => 25
Você também pode escrever callbacks como uma expressão de função:
applySideLength(function squarePerimeter(side) {
return side * 4;
});
Esse é um padrão útil em JavaScript porque o JavaScript foi projetado como um runtime de thread única, onde só uma chamada de função pode ser executada por vez. Durante a execução, o runtime não consegue responder a outros eventos nem continuar a execução até que a função tenha retornado.
Muitas chamadas de API (funções de I/O, temporizadores e listeners de eventos) usam um mecanismo assíncrono para colocar a chamada de função atual de lado até que o trabalho esteja completo. Ao término, uma função de callback é colocada na fila de mensagens, de modo que, quando o runtime está entre chamadas de função, as mensagens são processadas invocando a função de callback.
Também é útil usar funções de callback porque elas podem referenciar variáveis no escopo da sua closure, que não estão disponíveis para a função onde elas são invocadas mais tarde.
Os manipuladores de eventos são um caso de uso comum para callbacks em JavaScript. Eventos do navegador, como 'onload' ou 'onclick', são sinais que podem disparar funções a serem invocadas. O método addEventListener de um objeto do DOM (Modelo de Objeto de Documento) registra uma função de callback para ser invocada quando ele "ouve" que um evento aconteceu.
document.addEventListener('onload', function () {
alert('The webpage has now been loaded');
});
No Node.js, as funções de callback seguem uma convenção para controlar o fluxo de um programa. Elas seguem este padrão: o primeiro argumento da função de callback pode receber um Error ou null; o segundo argumento e os seguintes recebem os dados que a função chamadora foi projetada para enviar.
Se ocorrer um erro, o segundo argumento e os seguintes podem não estar presentes, então você não pode contar com a presença deles.
function operation(a, b, callback) {
// Work ...
if (/* an error occurs */) {
return callback(new Error('An error occurred'))
}
// On success:
callback(null, data)
}
function callback(error, returnedData) {
if (error) {
// An error occurred, handle it here.
return
}
// No error occurred, continue with the returned data.
}
operation(1, 2, callback)
Você vê esse padrão com frequência ao lidar com funções assíncronas para ajudar no controle de fluxo.
Funções comuns de Array usam funções de callback para definir seu comportamento:
Array.prototype.forEach:
Aceita um callback, que aplica o callback a cada elemento de um array.
[1, 2, 3].forEach(function (element) {
doSomething(element);
});
// => doSomething() is invoked 3 times, once with each element
Array.prototype.map
Aceita um callback, que aplica o callback a cada elemento de um array usando o resultado para criar um novo array.
[1, 2, 3].map(function (element) {
return element + 1;
});
// => [2, 3, 4]
Array.prototype.reduce
Aceita um callback, que aplica o callback a cada elemento de um array, passando o resultado adiante para a próxima invocação.
[1, 2, 3].reduce(function (runningSum, element) {
return runningSum + element;
}, 0);
// => 6