8

I'm a little confused, not about what callbacks are used for but because I see callbacks used in scenarios often where it seems like passing a function as an argument to another function isn't necessary because you can just invoke the function you want invoked after the code in the current function is finished executing. For example:

function hello( a , b ) {
    var result = a + b; 
    myFunction();
}

myFunction() {
    //code
}

hello(1,2);

What's confusing is, I've seen a lot of examples where a callback is being used in a scenario just as simple as the first code I wrote where it seems to me a callback isn't needed at all:

function hello(a, b, callback) {
    var result = a + b;
    callback();
}

myFunction() {
    //code
}

hello(1, 2, myFunction);

I used a callback there but I could've just called the function myFunction after the code executed without passing myFunction as an argument. I understand a framework or library doesn't know the name of the function you'll want called after code is finished executing so passing the function you want called later as an argument seems to make sense then but when you know the name of the function you want invoked after whatever code is executed in a function, why not just invoke it just as I did in the first example I gave? I would appreciate your help. Thanks

Barmar
  • 741,623
  • 53
  • 500
  • 612
codebmanj
  • 95
  • 8
  • 1
    If it was _exactly_ like the code you posted (adding a+b) then of course there is no reason. But sometimes functions do something asynchronously (like make an ajax call) and you want the function to wait until the ajax call is finished. (like when you want the callback to act on data you receive) – Cave Johnson May 27 '16 at 01:03
  • 3
    Can you give an example of a callback you feel was unnecessary? Callbacks are typically used for asynchronous functions. – 4castle May 27 '16 at 01:04
  • 3
    It's now about synchronicity, but knowledge: caller usually does not know what to call; or scope - caller is defined in a different scope. – zerkms May 27 '16 at 01:05
  • The interesting thing is usually not the point that the function is called, but a) *when* it is called (often *not* just immediately after the function returns) and b) with what arguments it is called – Bergi May 27 '16 at 01:06
  • Maybe [this](http://programmers.stackexchange.com/questions/195825/why-do-we-need-callback-functions) will help you.. – choz May 27 '16 at 01:18
  • javascript can't pause execution mid-function, so unless you want to bring everything to a halt, you need a structure to cross the temporal divide, and a callback is good structure for doing so, especially with closure. – dandavis May 27 '16 at 01:27

3 Answers3

8

Benefit 1

One of the reasons callbacks are nifty is that you can call your function with any callback at all:

hello(1, 2, myFunction1);
hello(1, 2, myFunction2);
...
hello(1, 2, anyFunctionAtAll);

Whithout the possibility of passing a callback as an argument, your hello would be tied to always execute myFunction, since it's fixed on your function code.

Benefit 2

The other reason is that with callbacks you prevent blocking on long-running operations. You pass a callback to run after the function operations are complete, and while it is processing it cedes control back to the main event loop instead of blocking.

For example, if you are about to execute these operations:

hello(1, 2, myCallback);
console.log('Im not waiting for hello!')

In case your myCallback function spends too much time processing, the console operation is not going to wait for it to terminate its execution.


If you want to understand more, an know any other javascript caveats, I recomend this and this


Conclusion

If you think you won't benefit of one of this things, so callbacks are not necessary on your scenario.

inafalcao
  • 1,415
  • 1
  • 11
  • 25
  • He already understands that: "*I understand a framework or library doesn't know the name of the function you'll want called […] so passing the function you want called later as an argument seems to make sense*". He asks why you wouldn't just write `hello(1, 2); myFunction1(); hello(1, 2); myFunction2();`. – Bergi May 27 '16 at 01:08
  • This isn't a use case for callbacks. It could just as easily be `hello(1, 2); myFunction1();` – 4castle May 27 '16 at 01:09
  • @Bergi it's not what OP asked (see the first example and the question last phrases) "why not just invoke it just as I did in the first example I gave". And in the first example they explicitly invoked a function inside a caller function, not after it completed. Hence: a perfectly valid answer to what OP asked. – zerkms May 27 '16 at 01:18
  • 1
    @zerkms: I'm unsure - but yes, it's a badly phrased question. – Bergi May 27 '16 at 01:20
  • @4castle "This isn't a use case for callbacks" --- it pretty much is. – zerkms May 27 '16 at 01:20
  • Regarding "benefit 2", [not all callbacks are asynchronous](http://stackoverflow.com/q/21884258/1048572). And certainly the act of passing a callback doesn't prevent blocking. Please make that more clear. – Bergi May 27 '16 at 01:21
0

One reason why you can use it is that you can call your myFunction as anonymous function

function hello( a , b, callback ) {
    var result = a + b; 
    callback();
}

hello(1,2, function() {
   // your stuff here
});

Second reason is that what if you use third part API, for example you make API request to an endpoint and wait for response?

$.get('api/some/url', function() {
   // This is your callback that get function provides you
})

Or maybe you are using some library for example jquery

$("p").hide("slow", function(){
   // Callback that will be executed after.
});
Gh111
  • 1,362
  • 18
  • 19
-1

The example you've given above is not a great use case for callbacks, imo. You don't typically want to simply execute the callback function procedurally, you want that callback function to dictate the behavior of the containing function its being passed to. This way, the containing function can behave differently based upon its given context/state.

Here's an example:

function modifyArray(array, callback) {
  var modifiedArray = [];

  for (var i = 0; i < array.length, i++) {
    modifiedArray.push(callback(array[i]));
  }

  return modifiedArray;
}

Notice how the callback function isn't simply executed? It actually dictates the way in which that containing function modifies the parameter array's elements.

This way, you can write highly flexible functions that you can re-use throughout your codebase.

Igor Barsi
  • 64
  • 5
  • But couldn't I do this: function modifyArray(array) { var modifiedArray = []; for (var i = 0; i < array.length, i++) { modifiedArray.push(myFunction(array[i])); } return modifiedArray; } function myFunction() { } – codebmanj May 27 '16 at 01:50
  • If the array was going to be an argument to the callback, why couldn't it be an argument to myFunction? Is it because of reusability solely that in this case, a callback would be beneficial for? – codebmanj May 27 '16 at 01:54
  • 1
    @codebmanj It's about modularity. Think of functions like `.map()` and `.filter()`. If you pass the array to the function, it has to do all the iteration itself, instead of that being done by `map()`. – Barmar May 27 '16 at 02:05
  • @Barmar So you're saying why pass the array to a function has to do all the iteration itself instead of using a function already made to do the work such as "map"? – codebmanj May 27 '16 at 02:36
  • @codebmanj Exactly. The whole point of functions like `.forEach()` is so you don't have to write a `for(var i = 0; i < array.length, i++)` loop yourself. – Barmar May 27 '16 at 02:38
  • Exactly what @Barmar said. You could just contain all the iterating and modifying logic all inside "modifyArray". However, in that case that's all that "modifyArray" can ever do. If you ever want to have the ability to modify/re-use the logic in one of your functions, callbacks will save you. – Igor Barsi May 27 '16 at 02:38
  • Igor Barsi & @Barmer thanks a lot for that clarification. – codebmanj May 27 '16 at 02:46