Could someone explain, why do we use callback in JavaScript? I found examples, but they could be implemented by using the normal functions. What is the advantage of using it
Callbacks are used all over the place in JS, particularly in jQuery.
One place you need to use a callback is anywhere the language doesn't give you coordination. Coordination means code doesn't execute until the data it needs is ready. Synchronous calls are coordinated; the call doesn't return until the sub-computation is finished. Asynchronous calls don't give you coordination, so you need a callback.
Event-driven computation can be uncoordinated, so event handlers are callbacks:
<input id="a" /> <button id='add'>+</button> <input id="b" /> = <span id="c"></span>
<script type="text/javascript">
$('#add').click(
function() {
$('#c').text(parseInt($('#a').val()) + parseInt($('#b').val()));
}
);
</script>
In JS specifically, coordination for event dispatch (e.g. the DOM dispatchEvent, jQuery trigger and IE fireEvent methods) is left unspecified (except for nested DOM events, which are synchronous). If you trigger an event, the handlers may be deferred and execution immediately return to whatever is after the trigger. Event handlers are usually called synchronously, but they don't need to be.
JQuery effects usually take a callback to execute once they finish. Animation functions are asynchronous so that they don't block the rest of the script.
Callbacks are also useful for functions that define the outer part of some computation, but leave an inner part undefined. Here are some examples:
You can use callbacks to filter collections:
// get odd items
$([0,1,2,3,4,5,6,7,8,9]).filter(function (i) {return this % 2;})
// or:
$.grep([0,1,2,3,4,5,6,7,8,9], function (x, i) {return x % 2;});
Array.sort takes a callback so you can define how elements are compared.
[{name: 'foo', id: 1}, {name: 'bar', id: 5}, {name: 'baz', id: 3}]
.sort(function (a,b) {
return a.name.localeCompare(b.name);
})
Some of jQuery's DOM manipulation methods (such as append, prepend and wrap take a callback to construct an element based on context provided by the jQuery method. You could view the callback as providing an inner portion of a computation or as a matter of coordination: when the outer computation is started, the needed data to build the new DOM elements isn't available; the callback finishes the sub-computations to create the elements when the data becomes available.
setTimeout
and setInterval
both take callbacks to execute after a delay.
Starting with version 1.5, jQuery offers deferred objects as a way of managing multiple callbacks, with various execution dependencies between the callbacks.
A callback is very similar to a "continuation", which basically means "the rest of the computation". The difference is that a continuation represents the entirety of the rest of the computation while a callback represents the rest of a sub-computation. Continuations are part of a whole style of programming known as "continuation passing style" (CPS). With continuations, you can create all sorts of interesting control structures. For example, continuations can be used to implement exceptions and coroutines.
Depending on the features of the language engine (in particular, you need tail call optimization), CPS can offer a more efficient approach. Some control structures (such as coroutines) require tail calls, otherwise you'll get a stack overflow*.
Callbacks allow single-threaded operations (Javascript is single-threaded) to execute asynchronously.
The most obvious example is AJAX calls, where you have a callback that executes after the AJAX request is done. The AJAX request can take a while, and if it were a normal function call, the whole page would be frozen (can't scroll, can't select text, etc) while the request loads.
This is achieved through either setTimeout
or setInterval
which enqueues a function to be called at a later time while allowing other code to execute in between. So when you're waiting for that AJAX call to finish, other code (which includes the browser updating) is allowed to execute.
Since you want examples other than AJAX, the other common usage for the async nature is for animations. Callbacks are required for animations because it needs to allow the UI to draw.
Say you wanted to animate a div
100px to the right over 5 seconds. Your first instinct might say create a loop and sleep in between. But there is no sleep
in Javascript, and even if there was, it would just freeze the UI because nothing can happen while it's sleeping.
Instead, you need to do something along the lines of increment the position by 10, then call setTimeout
for 500 ms with a callback to execute the next frame. This would probably be done recursively.
An additional use would be just simply to pass functions as parameters, although I'm not sure if the term "callback" is appropriate for that use case. That is the way you've used it in your example, some_function
can be reused with a variety of functions used as callbacks, so sort of injecting code.
Another point is code testability.
Let's say you have this scenario:
function pushToDatabase(data) {
// do some API call...
}
function handleData(someData) {
// some logic
pushToDatabase(someData);
}
When unit testing maybe you don't want to look into the database if new data is available but just check if pushToDatabase
function was called with the right data, so it can be refactored to:
function pushToDatabase(data) {
// do some API call...
}
function handleData(someData, callback) {
// some logic
callback(someData);
}
and called with handleData(someData, pushToDatabase)
.
This could be a test with Jest:
const aModule = require('./aModule');
describe('aModule', () => {
it('should push data to a database', () => {
const mockFn = jest.fn();
const myData = 'Hello!';
aModule.handleData(myData, mockFn)
expect(mockFn).toHaveBeenCalledWith(myData);
});
});
Link to working Repl.
Callback itself, as the name suggests (call - back) whenever you need to call a function after the execution of the first one, in those scenarios we need to use a callback. Basically the use of callback helps us when we need to use the result of the first function into another function and of course we can use it in a direct way but what if the first function did not respond to any result and we have already passed it to lower function then it will results to undefined and later if one had tried to mutate that passed value it will result in error like can not mutate or assign value of undefined .
function first(){
//any call or request that is giving us result say abc
function second(abc){
//mutate abc, it can be either array, object or can be another function
}
}
In these scenarios, we need to use call back as the first function will result in abc but no one knows how much time it will really take.
and apart from callback one should use promises or async/ await to make your code more modular and looks more like in synchronous ways