What is a callback?

Asked

Viewed 72,185 times

177

I see in many codes and even architectures the word callback, I see that it is in Javascript functions.

  • But what is?
  • How is it used?
  • Why?

I’d like an example of real use.

4 answers

189


Callback is a function that is used as "callback". It is typically passed as an argument from another function and/or call when an event happens, or when a piece of code receives a response that it has been waiting for.

This is very common in client and server-side javascript (Nodejs) but not only. The callback function is often asynchronous in that it is called as a consequence of another code that is running in the background. The great advantage is that so the computer can process other processes while the answer does not arrive and thus need to stop everything waiting for that answer.

A classic example is an event headphone that calls a function when the event happens:

function callback(e) {
    alert('Aconteceu um evento ' + e.type);
}
window.addEventListener('click', callback);

This callback will be called when you click on the window. Until this happens the processor will process other things that happen in the application.

Example: http://jsfiddle.net/D2PuH/


Another example is an ajax call, which prompts the server and runs the function when it receives the response.

This function is a "callback" function. In the example below (http://jsfiddle.net/skQr7/) I called him minhaCallBack.

function minhaCallBack(returnhtml) {
    $("#result").html(returnhtml);
    $("#loadingimg").hide();
}

$(document).ready(function (e) {
        $.ajax({
            url: form_url,
            type: form_method,
            data: form_data,
            cache: false,
            success: minhaCallBack
        }); 
});

Yet another example (http://jsfiddle.net/V3wDF/) is an animation that calls the callback at the end of the animation to be complete:

function completa() {
    alert('Este alert está dentro da função "callback"');
}
$('div').animate({
    'height': '200px'
}, {
    duration: 2000,
    complete: completa
});

Another example yet, to try to clarify more after appearing one more question on the subject.

I’m going to make an analogy between synchronous code and asynchronous code.
Imagining this situation:

Problem:

How to turn a number into string format, with too long decimal part that must be converted into dollars, and check if a given customer is entitled to discount.

Synchronous solution:

To solve this problem synchronously we need to know the initial value and the exchange rate before to begin the calculation. This is not always so, but for the example let’s assume that we know the following:

var valorInicial = "1003,087293487";
var descontoCliente = "5%";
var cambio =  1.1158; // 1 EUR = 1.11580USD

so we can do the transformation in a simple way:

var valorInicialEmFormatoNumerico = Number(valorInicial.replace(',', '.'));
var valorComDescontoAplicado = valorInicialEmFormatoNumerico - (valorInicialEmFormatoNumerico * parseFloat(descontoCliente) / 100);
var valorEmDolares = valorComDescontoAplicado * cambio;
var totalComDuasCasasDecimais = valorEmDolares.toFixed(2);

Thus the result is obtained with synchronous steps, and gives 1063.28

Asynchronous solution:

Imagine now that we need to do the same thing, but we do not have all the information available, because the exchange rates change constantly, we cannot have the discount available to all possible customers, and not even the initial price because we have to ask our supplier first.

How to do?

In this case we have to do the asynchronous thing, that is to run part of the code, wait for answers, run one more piece and wait for another answer, etc...

We can say that when we asked something to an outside service we probably make an ajax request. And now we need a tool to get the answer, that’s where callbacks come into play.

When I send a question to an external service I have to tell him how to contact/inform me with the result. A common way is to send a function with the request so that it is run when the answer arrives.

send a request function for it to be run when the answer arrives

If I send a function to a setTimeout, I tell setTimeout what code is running when the time has run out. This function may have the name we want, but its functionality, its type is callback:

var fazerAlgo = function(){ alert('O tempo chegou ao fim!'); }
setTimeout(fazerAlgo, 2000); // correr ao fim de 2 segundos

Returning to the example of accounts:

To do the previous calculation with asynchronous logic we have to chain things and depend on functions that are being called with waiting times between them. So we have to chain everything, for example like this:

pedirPrecoAoFornecedor(numeroProduto, function(respostaDoFornecedor) {
  var valorInicialEmFormatoNumerico = Number(respostaDoFornecedor.replace(',', '.'));
  pedirInformacaoDesconto(numeroCliente, function(descontoCliente) {
    var valorComDescontoAplicado = valorInicialEmFormatoNumerico - (valorInicialEmFormatoNumerico * parseFloat(descontoCliente) / 100);
    pedirCambioDaHora('USD', function(valorDoDolar) {
      var valorEmDolares = valorComDescontoAplicado * valorDoDolar;
      var totalComDuasCasasDecimais = valorEmDolares.toFixed(2);

      // !! agora temos o resultado!! 
      alert(totalComDuasCasasDecimais + 'USD');

    })
  })
})

This function chaining is necessary because each callback will be called when the external service wants it. For example the function pedirPrecoAoFornecedor takes two arguments: the product number and a function. As I know that what I will receive is the price of the product I have already put it as variable name, to facilitate reading. This function I step to pedirPrecoAoFornecedor is therefore a callback, a mechanism for the outside service to give me back what I need.

  • 8

    +1 excellent answer, examples for you, you should write a book :P

  • 4

    It was well explained, thank you!

  • 4

    Very good explanation, congratulations.

61

Callback (or callback, in Portuguese) is a flow control mechanism that aims to benefit asynchronous processes.

The main idea is to release the application so that other actions are taken without it waiting for the return of synchronous processes, waiting for a remote response, or (if the platform/framework in support use threading) with high processing consumption if you opened a thread separated to wait for the answer.

In a traditional mechanism, the synchronous request (and consequent wait) for a resource would thus be in pseudocode:

Var B = A.SoliciteRecurso();
Print B.Nome;

Let’s say that operations within SoliciteRecurso() take a minute. in this case, your application will be all this time waiting for the answer.

Now, an asynchronous operation via Callback:

Objeto.AssinarRetornoDeSoliciteRecurso += ProcessarRetorno;
Var B = A.SoliciteRecursoAssincrono();

função ProcessarRetorno(Objeto B)
{
    Print B.Nome;
}

In this case, the application control is returned right after the method SoliciteRecursoAssincrono(). When, and if, the object A generate the event that fires AssinarRetornoDeSoliciteRecurso, the method ProcessarRetorno will be called.

Several modern technologies use this feature. For example, this snippet on AngularJS:

function directoryController($scope, $http) {
    'use strict';
    $scope.url = 'backend/services/dir.aspx?q=';

    $scope.search = function() {
        $http.post($scope.url + $scope.keywords).
            success(function(data, status) {
                $scope.status = status;
                $scope.data = data;
                $scope.listOfUsers = data;
            }).
            error(function(data, status) {
                $scope.data = data || "Request failed";
                $scope.status = status;
            });
    };

Basically says:

  • In the method search, access this URL via method Post.
  • Successful case (event success), proceed in this manner.
  • If an error has occurred (event error), proceed in this other way.

The benefits brought by asynchronous calls are clear: You have a more responsive application and lower processing consumption.

On the other hand, it introduces new paradigms that you need to treat in your code, such as asynchronous flow control (for example, 'only advance if you have received the successful return of the method M.')

30

When an event (click on a button, page load completed, mouse over any element, etc.) happens, the browser warns all listeners (listeners), calling your functions Calback.

window.addEventListener("load", function(){
    console.log("Eu sou uma função de callback, prazer!");
});

In the above example, we added an "onload" event listener in the window (i.e., we want the browser to call our anonymous function - function(){...} - as soon as the page finishes loading into the user’s computer memory).

Basically, we can do many things with a callback function: exchange a text on the page, hide elements, among many other uses.

8

But what is?

A function of callback is that function that can be called by the method that receives it at the time it wishes.

In a pseudo language, it would be something like this:

funcao(Function funcaoCallback) {
    // funcao faz diversas coisas
    funcaoCallback.call(); // chama a função passada por parâmetro
}

This concept is commonly associated with the Javascript language due to the popularity of this language, since from its beginnings Javascript accepts the passage of methods as a parameter to a function. Other popular programming languages only came to have this type of characteristics many years later, as happened with Java.

How is it used?

There are different ways to use it in each language and conceptually it can be used in countless ways.

Let’s go to an example in Java. In Java 8 you can pass a method from any class to a method that accepts the parameter Supplier. Imagining that we have this method in a class called RetryMethod:

public void run(Supplier<T> callbackFunction) throws Exception {
    try {
        // código fazendo inúmeras coisas
        callbackFunction.get(); //chamada da função recebida por parâmetro
    } catch (Exception e) {
        log.warn("Command failed", e);
        return retry(function);
    }
}

And to pass the function for this method:

RetryMethod<Object> retryMethod = new RetryMethod<>();
retryMethod.run(() -> service.metodoChamadoPorCallback(qualquerParametro));

So whatever the method metodoChamadoPorCallback does inside the class with variable name service, the method run class RetryMethod has full control of when to call her.

Why?

As I said earlier, the possibilities are endless.

In the above example, the code used can give control to the class RetryMethod of the method metodoChamadoPorCallback be called different times in case of a Exception within it, making several attempts (retries). This class RetryMethod could receive any kind of function in which the goal is to repeat the call from the function passed to callback, no matter what the function does.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.