I'm trying to understand JS and I'm really confused by the callback pattern.
function one(){
alert("I'm one!")
}
function total(arg, callback){
setTimeout(function() {alert("I'm "+arg);}, 1000);
callback();
}
total('all', one);
versus
function one(){
alert("I'm one!")
}
function total(arg){
setTimeout(function() {alert("I'm "+arg);}, 1000);
one();
}
total('all');
What is the benefit of passing one() as a parameter vs just calling it from within the function?
If you know that you're always going to call one, there's no need to accept it as an input parameter; you can just go ahead and call it.
The ability to accept callbacks allows you to easily write loosely coupled code.
You are, for instance, passing a callback to setTimeout in your code example. setTimeout knows to wait a given number of milliseconds before a function is called, but it doesn't know which function to call.
Passing in callback functions allows you to dynamically affect the flow of the program. Additionally, you could pass the outcome of total as a parameter to callback, which is often used to enable asynchronous programming.
function one(){
alert("I'm one!")
}
function total(arg, callback){
setTimeout(function() {
if (callback) {
callback();
}
}, 1000);
}
I suspect that your examples are not what was intended to showcase what a callback is. Does this make more sense?
function cb(arg){
alert("I'm "+arg+"!")
}
function total(arg, callback){
setTimeout(callback, 1000, arg);
}
total('one', cb);
Callback argument allows you to define custom interaction. It's commonly used with any asynchronous operation to allow reacting of state change (for example when operation is done, or errored).
One example of that may be an AJAX call (here with jQuery for simpliciy):
var request = $.ajax({
url: "script.php"
});
// this allows you to specify custom action handling
request.done(one);
Related
I am new to javascript, I have gone through tutorials about callbacks, but I don't see any that answers this, both method below offers the same results, the only difference I see is callback allows dynamically passing in a callback function.
Are there other advantages, I am missing?
Thank you.
Callback
function logOne(callback) {
setTimeout(() => {
console.log("one");
callback();
}, 1000);
}
function logTwo() {
console.log("two");
}
logOne(logTwo); // one, two
No Callback
function logOne() {
setTimeout(() => {
console.log("one");
logTwo();
}, 1000);
}
function logTwo() {
console.log("two");
}
logOne(); // one, two
Your first example is more flexible: You can use any callback, not just logTwo.
Both have their uses, it depends on whether you need the flexibility or whether logOne should be specifically tied to logTwo.
Callback of function: If you want to do some operation on some event
Like show time on click of a button. Then you override onclick
function for that button. So whenever (independent on time) that
button is clicked, that application internal framework will call
onclick event and your onclick function will be called.
Normal function : Every function is normal function
Calling a function is when you actually do the function.
Passing a function is when function A needs function B in order to
work. So when you call function A, you pass it function B as an
argument. In this case you are not calling function B, instead you are
providing it to function A so that function A can call it.
Your second example create a tight coupling between logOne and logTwo functions. This way you end up with a logOne function that can't be reused since it only works with one exact function.
By passing a callback, you make your function more flexible and generalized. Now it is able to work with a wide range of other functions as long as they have the same "shape" - same number of arguments in a same order.
Learning javascript and wanted to get more clarity regarding callbacks.
In the following code snippet,
function do_a( callback ){
// if callback exist execute it
callback && callback();
}
function do_b(){
console.log( 'do_b executed' );
}
//one way
do_a( function(){
do_b();
});
//other way
do_a(do_b);
Is there a difference between the two ways the do_a() is called. One passes a pointer to the do_b function, the other passes a function which executes the do_b function. All the examples i've seen use the first way. Is that more preferred style wise?
The first way just creates an extra anonymous function that calls the second function. This is useful if you want to perform actions before or after calling the callback, e.g.
do_a( function(){
console.log("I'm going to call the second function...");
do_b();
console.log("Second function is done.");
});
Otherwise, I can't see any point in this extra function and the second way is better.
you don't have to pass it as an argument. Directly call it.
function abc(){
a = "function abc";
console.log(a);
cde();
console.log(a);
}
function cde(){
a="function cde";
}
abc();
So i don't really understand the point of "callback".
Here is an example of callback:
function sayBye(){
alert("Bye!");
}
function saySeeYou(){
alert("See you!");
}
function sayHello(name,myfunc){
alert("Hello");
myfunc;
}
sayHello("Max",saySeeYou());
Whats the point of passing in a function when you can just call the function? like this code does the exact same:
function sayBye(){
alert("Bye!");
}
function saySeeYou(){
alert("See you!");
}
function sayHello(name){
alert("Hello");
saySeeYou();
}
sayHello("Max");
Whats the point of passing in a function when you can just call the function?
Usually, callbacks Javascript are used in Javascript for code that you want to run in the future. The simplest example is setTimeout: if you call the callback now then the code runs immedieately instead of after 500 ms.
//prints with a delay
console.log("Hello");
setTimeout(function(){
console.log("Bye");
}, 500);
//no delay this time
console.log("Hello");
console.log("Bye");
Of course, it would be really neat if we could write something along the lines of
//fake Javascript:
console.log("Hello");
wait(500);
console.log("Bye");
But sadly Javascript doesnt let you do that. Javascript is strictly single-threaded so the only way to code the wait function would be to pause the execution of any scripts in the page for 500 ms, which would "freeze" things in an unresponsive state. Because of this, operations that take a long time to complete, like timeouts or AJAX requests usually use callbacks to signal when they are done instead of blocking execution and then returning when done.
By the way, when passing callbacks you should only pass the function name. If you add the parenthesis you are instead calling the function and passing its return value instead:
//When you write
foo(10, mycallback());
//You are actually doing
var res = mycallback();
foo(10, res);
//which will run things in the wrong order
Your code is not correct as Felix Kling already pointed out. Besides this, passing a function instead of calling one directly allows you to insert different behavior, your code is more decoupled and flexible. Here an example:
function sayBye(){
alert("Bye!");
}
function saySeeYou(){
alert("See you!");
}
function sayHello(name,myfunc){
alert("Hello");
if (myfunc) {
myfunc();
}
}
sayHello("Max",saySeeYou);
// I'm inserting a different behavior. Now instead of displayng "See you!"
// will show "Bye!".
sayHello("Max",sayBye);
You are doing it wrong, you should do like bellow
Don't call the function just pass the function as callback
use this
sayHello("Max",saySeeYou); //here the second parameter is function
instead of
sayHello("Max",saySeeYou());//This will put the result of saySeeYou as second parameter
in say hello call the functiom
function sayHello(name,myfunc){
console.log("Hello");
myfunc();
}
I have a function that stores several values from a HTML form, and that must work individually in order to store that info in any situation I need (ie before inserting on DB, or before udating info on DB...)
I need to be able to tell the system to execute this function ('storeValues'),and then execute any other (could be 'createNewClass', 'updateExistingClass'... whatever).
How can I sequence this? I tried here to store values first and, WHEN DONE, execute another function aleting about a value, but it says "storeValues() is not defined", and it is defined:
$('.tableClassHeader').on('click', '.createClass', function(){
storeValues().promise().done(function(){
createNewClass();
});
});
function storeValues(){
cl_year = $('.newClassForm').find('select[name=cl_year]').val();
cl_course = $('.newClassForm').find('select[name=cl_course]').val();
}
function createNewClass(){
alert(cl_year);}
I mean that storeValues function SHOULD BE a separate function with the possibility of being called from any other place, I know this problem could be solved by executing "createNewClass" from the "storeValues" function, but there will be times that I need to execute "updateClass" after "storeValues", not "createNewClass"
You can use a callback like this, if your storeValues is not synchronous like in your example:
$('.tableClassHeader').on('click', '.createClass', function(){
storeValues(createNewClass);
});
function storeValues(callback){
cl_year = $('.newClassForm').find('select[name=cl_year]').val();
cl_course = $('.newClassForm').find('select[name=cl_course]').val();
callback();
}
function createNewClass(){
alert(cl_year);
}
If it is synchronous, just calling createNewClass after storeValues is enough.
What this does is:
offers you the ability to pass a function of choice to the storeValues
inside storeValues it calls the callback function passed as parameter
If you need to execute your function with a different scope you can use call or apply.
Another way to do this, without callbacks would be using
http://api.jquery.com/promise/
http://api.jquery.com/jQuery.when/
http://api.jquery.com/deferred.promise/
Example as seen here http://jsfiddle.net/47fXF/1/ :
$('.tableClassHeader').on('click', '.createClass', function(){
$.when(storeValues()).then(createNewClass);
});
function storeValues(){
var dfd = new jQuery.Deferred();
setTimeout(function(){
console.log('storing values');
cl_year = $('.newClassForm').find('select[name=cl_year]').val();
cl_course = $('.newClassForm').find('select[name=cl_course]').val();
dfd.resolve();
}, 1000);
return dfd.promise();
}
function createNewClass(){
alert("trololo");
}
Added the setTimeout to simulate asynchronicity.
If your storeValues is making only one ajax request using jQuery, then you can return it directly as shown in the API documentation.
Also make sure to call resolve(), reject() appropriately.
Call like this . it first call the storeValues after executes the createNewClass function
$('.tableClassHeader').on('click', '.createClass', function(){
storeValues(function() {
createNewClass();
});
});
function storeValues(callback){
cl_year = $('.newClassForm').find('select[name=cl_year]').val();
cl_course = $('.newClassForm').find('select[name=cl_course]').val();
callback();
}
I have a functions which should run one AFTER the other, such:
function cutTomatoesAlone(Kg){
// slice my stuff
}
function cookTomatoes(Minutes){
// boil my stuff
}
I call them such:
cutTomatoesAlone(15) // 15kg, need 3 hours!
cookTomatoes(10); // need 10 minutes
But the cookTomatoes(10) finish before my cutTomatoesAlone(15).
How to run cutTomatoesAlone(15) first and when finished, then run cookTomatoes(10) ?
Edit: cutTomatoesAlone() load an external JSON. cookTomatoes(10) work on it.
Learn about promises and deferred objects. Every Ajax function in jQuery returns a promise, so you can easily chain your function calls.
For example:
function cutTomatoesAlone(Kg) {
return $.getJSON(...); // return the promise provided by $.getJSON
}
// called as
cutTomatoesAlone(15).then(function() { // attach callback
cookTomatoes(10);
});
In case of an Ajax call, the promise is resolved once the response was successfully retrieved.
You need the method The setTimeout() which will wait the specified number of milliseconds, and then execute the specified function.
function cutTomatoesAlone(Kg){
// slice my stuff
setTimeout(function() {
cookTomatoes(10)
}, delay);
}
If your functions are independent, it should work the way you expect, assuming you're not doing stuff like making http get requests asynchronously.
If you are, what you need to do is call the second function when the first one returns from its request, using JQuery's $.done() function.
Give cutTomatoesAlone a callback.
var cookingTimePerKg = 10;
function cutTomatoesAlone(Kg, Callback) {
// slice my stuff
// when done and a callback is defined do the callback
if(Callback) Callback(Kg*cookingTimePerKg);
}
Then you could do the following:
cutTomatoesAlone(15, cookTomatoes);
The callback could also be fired on the onComplete of the (potential) XHR request.
Some Function object prototype tuning would make it easier to read
Function.prototype.after = function(callback){
this();
if( typeof(callback) == "function")
callback();
}
a = function(){alert(1)};
a.after( function(){alert(2)} )
So with cooking subject:
var cutThem = function(){
cutTomatoesAlone(15) // 15kg, need 3 hours!
}
cutThem.after( function(){
cookTomatoes(10);
});
this is a proposal for general purpose, when ajax loads are on the game it's better to use their "whenDone" option to supply them a callback.
$("#basket").load("url.extension", {kilos: kg},
function(){
cookTomatoes(10);
});