Javascript Callback functions vs just calling functions - javascript

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();
}

Related

Function with a callback

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();

Storing function call results for later referall

I've been trying to read as much as I can about javascript callbacks and jquery deferred objects but apparently things just aren't clicking for me. It seems to make a vague amount of sense when I read through it and practice examples, but when I try to apply it to my specific problem, I'm just hitting a wall. If anyone can understand what I'm trying to do and offer ideas, it would be much appreciated!
Here's some existing code:
$(document).ready(function() {
firstFunction();
secondFunction();
});
For the sake of keeping things simple here, I won't get into what firstFunction() and secondFunction() do, but suffice it to say that they both perform asynchronous work.
Here's my problem:
firstFunction() is dependent on the document being ready so needs to be inside $(document).ready(function() { }. secondFunction() isn't dependent on $(document).ready(function(), but should only execute after firstFunction has completed. I'm hoping to do all the computation for secondFunction() before the $(document).ready(function() { } block, but only execute it after firstFunction() has completed. This way firstFunction and secondFunction will execute in a more visually seamless manner. So basically, I'd like to do something like the following pseudo code:
var deferredSecondFunction = secondFunction().compute().defer(); //perform computation for secondFunction but defer execution
$(document).ready(function() {
firstFunction().done.execute(deferredSecondFunction().execute()); //finally execute secondFunction once firstFunction has completed.
});
Does anyone know if this is even possible? An important caveat is that I need to do this without the Javascript Promise object, since, for reasons outside the scope of this question, the webkit I'm working with is an old version. If anyone could help me understand this it would be appreciated!
The code shown uses a callback function and a self-invoking anonymous JavaScript function such has:
var calculatedObject;
(function(){
// Will be executed as soon as browser interprets it.
// write code here & save your calculations/operations
calculatedObject = { ... };
})();
function firstFunction(callback){
// Do stuff
callback();
}
function secondFunction(){
// Do more stuff
// Use your calculations saved in the calculated object.
}
$(document).ready(function(){
firstFunction(secondFunction);
});
This way the second function will only be called at the end of the first one.
you can use a callback..
function f1(){
//do some stuff
}
function f2(callback){
// do some async stuff
callback();
}
f2(f1);
this example passes one function to another function. the second function then calls the first whenever it's ready.

setTimeout nuances in Node.js

I'm trying to understand how the callback function works inside the setTimeout function. I'm aware the format is: setTimeout(callback, delay) I wrote a little test script to explore this.
test1.js
console.log("Hello")
setTimeout(function () { console.log("Goodbye!") }, 5000)
console.log("Non-blocking")
This works as expected, printing Hello <CRLF> Non-blocking and then 5 seconds later, prints Goodbye!
I then wanted to bring the function outside of the setTimeout like this:
console.log("Hello")
setTimeout(goodbye(), 5000)
console.log("Non-blocking")
function goodbye () {
console.log("Goodbye")
}
but it doesn't work and there isn't a 5 second delay between Non-blocking and Goodbye!, they print straight after each other.
It works if I remove the brackets from the function call in the timeout, like this:
setTimeout(goodbye, 5000)
but this doesn't make sense to me because that's not how you call a function. Futhermore, how would you pass arguments to the function if it looked like this?!
var name = "Adam"
console.log("Hello")
setTimeout(goodbye(name), 5000)
console.log("Non-blocking")
function goodbye (name) {
console.log("Goodbye "+name)
}
My question is really, why doesn't it work when there are parameters in the function, despite the fact the setTimeout is being provided with a valid function with the correct syntax?
By putting the parentheses after your function name, you are effectively calling it, and not passing the function as a callback.
To provide parameters to the function you are calling:
You can pass an anon function. setTimeout(function(){goodbye(name)}, 5000);
Or, you can pass the arguments as a third parameter. setTimeout(goodbye, 5000, name);
Look at this question: How can I pass a parameter to a setTimeout() callback?
No matter where you place it, goodbye(name) executes the function immediately. So you should instead pass the function itself to setTimeout(): setTimeout(goodbye, 5000, name).
When you use it like this:
setTimeout(goodbye(), 5000);
it will first call goodbye to get its return value, then it will call setTimeout using the returned value.
You should call setTimeout with a reference to a callback function, i.e. only specifying the name of the function so that you get its reference instead of calling it:
setTimeout(goodbye, 5000);
To make a function reference when you want to send a parameter to the callback function, you can wrap it in a function expression:
setTimeout(function() { goodbye(name); }, 5000);
You can use parantheses in the call, but then the function should return a function reference to the actual callback function:
setTimeout(createCallback(), 5000);
function createCallback() {
return function() {
console.log("Goodbye");
};
}

Store jQuery scripts in JS Variable

I have a function with a variable called callback
function test(callback){
// Some code
callback;
}
When I call this function I used to insert a one liner into callback
eg. test($('#elem').hide());
Now I want to put multiple lines in here as the callback. I tried this but it does not appear to work.
var resetc = function(){
$('.access').removeClass('viz');
window.setTimeout(function(){
$('.access').find('.input.wheel').removeClass('viz');
$('.access').find('input').removeAttr('disabled');
},1000);
}
test(resetc);
As you are passing the function reference. You can use the callback variable to execute the function which it is referring. like
function test(callback) {
// Some code
callback();
}
You statement test($('#elem').hide()); is having no effect as you are passing the output of $('#elem').hide() to your method test and statement callback; actually is not performing anything.
You need to change your function call for test($('#elem').hide()); with
test(function() {
$('#elem').hide();
});
Your initial code doesn't do what you think. To call a callback, you need to put () after it:
function test(callback) {
// some code
callback();
}
If you fix that, test(resetc); will do what you want.
The reason you didn't notice this in your first test is because when you write
test($('#elem').hide());
you're executing $('#elem').hide() before calling test, it's not being done when test runs the callback. You need to pass a function to defer the execution until the callback is called:
test(function() {
$('#elem').hide();
});

Sequence several functions on jQuery

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();
}

Categories