Javascript callback functions differences - javascript

I would like to know the difference between 2 implementations of callback functions.
This:
$("#button").on('click', function () {
//do something
});
Versus having the function already defined.
$("#button").on('click', btnFunction);
function btnFunction() {
//do something
}
Are there any implications with one compared to another? Performance-wise is one faster?

The first uses an anonymous function and the second does not. There's no difference in both.
See:
Why do you need to invoke an anonymous function on the same line?

Some folks prefer the second form because it gives a function name when using the debugger and tracing, but there are ways to get the same functionality in the first form.
If you are attaching and removing the event handler based on changing conditions, the second form is much easier to maintain, however.

There's no difference at all, and there's no performance issue with neither one of them. The only difference is that in one of them you're defining the callback function as an anonymous function, this way you cannot reuse it.
The other way, where you define it else where and named it and then pass it as a callback, you're defining a function that you can later reuse in another part of your code.
For example: if you want to do something when the document is ready, and then do se exact same thing when some one press a button you can use something like this:
function getData() {
//do something
}
$(function() {
// Call the function once the DOM is ready
getData();
});
// Call the same function when the button is clicked
$("#refresh_button").on('click', getData);

In most cases the first one will be used, called Anonymous Functions
The second one will be used when the function is not only used inlined here, but also needs to be reused somewhere else.
But anyway it could be a personal preference.

The only real difference you could see is that stack trace (if an exception is thrown for example) will be better, i.e. easier to debug, when using the second one.

Just reuse-ability.
In the second case, you could call btnFunction() somewhere else if need be.

Related

JavaScript callback sequence of operations

I am reading a book called You don't know JS: Async and Performance. They give the following example of a problem with nested callbacks and I was wondering if someone could elaborate on the specifics for me.
doA (function(){
doC();
doD(function(){
doF();
})
doE();
});
doB();
According to the author, the code will execute in the order denoted alphabetically. Meaning doA, then doB ... . I may have been able to guess this based on experience, but I am trying to get a better grasp as to exactly why this happens.
Edit: I posted the question because the example in the book didn't make any sense to me and I was hoping to get some clarification. Maybe I should have just said that instead of trying to rescue the author with some explanation. I edited the question a little to try and make that clear.
Is it because the event loop runs for the entire outer "wrapper" first before it starts the inner wrapper?
No. If the order of execution really is A,B,C,D,E,F, then it is because that is how the functions are written to invoke their callbacks. If the functions were written differently, it could just as easily be A,C,D,E,F,B or A,C,D,F,E,B or, it could even just be A,B, if A does not accept a callback function.
All of this speculation...
Here is what I think is happening. The event loop is first created as doA and doB because JavaScript is not really "concerned" with the contents of those lines at first. When JavaScript runs the line doA(function... it then adds the callback function to the end of the event loop placing doC and doD behind doB.
... is more or less nonsense.
Here is a drastically simplified example:
function doA(callback) { callback(); }
doA(function () {
doB()
});
doC();
Here, the order is A,B,C because that is how A is written.
However, if we change doA so it invokes its callback asynchronously...
function doA(callback) { setTimeout(callback); }
... then the order changes completely to A,C,B.
This has nothing to do with JavaScript being "concerned" with any of the inner or outer code, or where JavaScript "chooses" to place the callbacks in the "event loop". These are not real things. JavaScript doesn't "choose" to do anything. It just executes your code. It's entirely about what each function does and whether the function accepts a callback and how that callback is invoked.

How can I pass a string, or list of function names to be processed as callbacks in Javascript

Done a bit of Googling, but not quite finding what I want.
In an effort to reduce the amount of JAvascript lines my applications requires, I am trying to use as many reusable functions as possible.
The problem of course is trying to make these functions and flexible as possible.
So I have a form which is dynamically expanded by a cloning function using jQuery. In order for this to work, there are a few additional functions which need to run, for example, to correctly initialise datepickers, on the dynamically created elements.
These requirements are different depending upon which form is being cloned.
So, I call my cloning function as follows:
$('.button').click(function (){
var thisID = $(this).attr('id').replace('add', '');
cloneDetails(thisID, initialiseDates);
});
The cloneDetails function looks like this:
function cloneDetails(cur_num, callBackFunctions) {
/// do loads of stuff ///
callBackFunctions();
});
In this instance, the cloning function will run and do what it needs, then it'll run a second function call initialiseDates
What I want to be able to do though is specify several function names to run after the cloning function, with a call such as
cloneDetails(thisID, 'initialiseDates, doSomethingElse, doAnotherThing');
So, stating a list of functions to run after the cloneDetails function has been run.
I don't think I am setting up the callBack method correctly, and don't know how I should be.
Help much appreciated.
EDIT: I don't want to bundle all these functions into a single function, the whole point is these functions should all be useable independently and/or together.
I can think of several approaches:
You can split the string and use eval(name+'()') in each name in the list. Note that eval() can be evil, security wise.
Instead of a string, why not pass the functions as an array? Simply iterate over arguments[1..n] (arguments is an automatic variable which contains all function arguments).
Use an anonymous function:
cloneDetails(thisID, function(){
initialiseDates();
doSomethingElse();
doAnotherThing();
});
I like the last approach because:
It's the most flexible
Readable
Only adds a few bytes of code where you need them
Most performant
Another option (if you're using jQuery > 1.7): You can use the jQuery.Callbacks function.
cloneDetails(thisID, $.Callbacks()
.add(initialiseDates, doSomethingElse, doAnotherThing));
function cloneDetails(cur_num, callBackFunctions) {
/// do loads of stuff ///
callBackFunctions.fire();
});

wait for async javascript function to return

I am using a function supplied by a third party library. This function takes a callback function as a parameter, but I would like to wait for this callback to be called before continuing. Is there a standard / accepted way to do this?
I am not sure if this is a possible solution for you but you can achieve the desired result by breaking your code into 2 functions.
Suppose this is what you intend to do:
Basically this is your original function:
function origFunc() {
codeBeforeThirdPartyFunc();
ThirdPartyFunc(oldCallBackFunc);
Wait();
codeAfterCallBackFunc();
}
You can modify the code flow with something like:
function newFunc() {
codeBeforeThirdPartyFunc();
ThirdPartyFunc(newCallBackFunc);
}
function newCallBackFunc() {
oldCallBackFunc();
codeAfterCallBackFunc();
}
This will eliminate the wait loop. And as far as I know, busy waiting doesn't work in IE (because ? God only knows)..
Here's another method of loading jQuery asynchronously, which doesn't depend on another script.
I don't know if Sharad's solution would work in all cases (for instance if you function calls are so far chained that you have to pass data as variables instead of parameters). Same problem with global variables. JavaScript just doesn't have a "wait" ability.
Although I had a similar problem and with jQuery, I ended up with a MacGyver type solution that gives you tons of control on when javascript functions execute. I just posted it here as an answer to my own question (but I it's an answer that's not checked - look for my username Emile): How to get a variable returned across multiple functions - Javascript/jQuery

Javascript Event Synchronization

I'm building a concert calendar that's very heavy on javascript (using jQuery). I'm having trouble synchronizing various events throughout the app, and I'm looking for suggestions for how to do this.
An example of a simple use case:
User clicks a month
Calendar skips to that month
An example of a more complex use case:
User selects an artist
Calendar determines the date of that artist's first show
Calendar skips to that month
Calendar highlights that artist's show(s)
One occasional problem is that the new month isn't yet rendered by the time I try to highlight the artist's show(s). Thus, the show isn't highlighted even though these functions are called in order. Obviously, using setTimeout() is pretty hacky, and not guaranteed to work.
So first, a simple question -- would it ever be possible (even in Chrome) for the following function to run out of sequence?
function steps(){
stepOne(); //TAKES 30 SECONDS
stepTwo(); //TAKES < 1 SECOND
}
Second, a related simple question:
If placed at the end of a function, will a JS callback ALWAYS run after
everything else in the given function has finished running?
If so, I could nest each function as a callback of its previous function. But that would likely become unwieldy, once you consider all the different use cases.
Here's an approach I'm considering:
1) Allow each function an optional callback parameter. If it's present,
call it at the very end of the function.
2) During a UI refresh, create an array, and stack any functions to be
called within this array.
3) Once this "script" is completed, iterate through the array, calling
each function in the order it was added, using the next function
as the previous function's callback.
I imagine this would ensure that all the functions are called in order.
Another approach is to attach event listeners using
$(document).bind("listener.name", fnCallback);
And then calling
$(document).trigger("listener.name");
Whenever that event occurs.
However, I'm guessing this would be kind of unwieldy as well, considering different events might need to call different sets of functions depending on the use case. I could always call
$(document).unbind("listener.name");
before adding new events to it, but again -- I'm leaning toward creating sort of a master "script" as I suggested in the first approach.
Hopefully this isn't too vague -- any feedback? Any experience with complex UIs that had to synchronize various events?
Thanks very much,
Michael
Your approach #1 is the best way, and the most natural using jQuery. Most functions that act on the user interface and do something accept a callback function parameter, which gets called after the function has executed.
Where you are doing things not implemented in jQuery following the same pattern will make your code more readable. dominic's answer is a good terse example:
function steps(){
stepOne(stepTwo);
}
function stepOne(callback){
var AsyncDone = function() {
//any Synchronus Things here
callback();
}
someAsyncFunction( params, AsyncDone );
}
Try passing in the function to be called back to as an argument
function steps(){
stepOne(stepTwo);
}
function stepOne(callback){
var AsyncDone = function() {
//any Synchronus Things here
callback();
}
someAsyncFunction( params, AsyncDone );
}
The last approach, of using custom events, is the best approach in my humble opinion.
Design various components and events and let them interact with each other.
E.g. Let's say you have a Calendar object.
var calendar = function()
{
var pub = {};
pub.highlightRow = function(row) {};
pub.getRowByContent = function(content) { };
pub.selectMonth = function()
{
//your code to actually select month.
//Once all the necessary DOM work is done, fire the
//monthSelected event (namespacing the event so as to avoid the clash with other events).
$(document).trigger('calendar:monthSelected');
};
return pub;
}();
Now your artist search method may look like,
function searchArtist(artistName)
{
$(document).bind('calendar:monthSelected'), function()
{
calendar.highlightRow(calendar.getRowByContent(artistName));
}
);
calendar.selectMonth(getShowMonthByArtist(artistName));
}
You can use javascript's then() method to synchronize the functions and have them execute in the order that you want, like so:
function steps() {
stepOne().then(function() { stepTwo(); })
}

Why is dynamically modifying a JavaScript function's code mid-execution a bad thing?

A few days ago, I asked a question regarding dynamically modifying a function's code midway through the outerlying script's execution and I was told to completely forget ever coming upon the notion. I'm not sure I understand why that is. Let me give an example:
<script>
var display = function(msg)
{
alert(msg);
}
// Now, at the moment, the display() function
// is receiving a single parameter and alerting
// it to the user. I'm now going to use eval()
// to modify the display() function.
eval('display = ' + display.toString().replace('alert(', 'document.write('));
// Now, the display() function writes its parameter
// to the document as opposed to alerting it.
</script>
I realize this is a rather trivial example, but there must surely be some use that can be derived from being able to dynamically modify a function, something so useful by itself.
Although this may do what you need it to do, 6 months from now you (or the person maintaining your code) will be going "WTF?!"
If your use case is to alert or write based on some condition, why don't you write two different functions? Or have your function take another parameter that decides the output mode. Or pass in a function as a parameter that performs the actual output. Something, you know, a little more on the sane side. ;-)
There are cases where it could be useful to change a function's behavior, but there are better ways to do it. In your example, you could create new instances of the function that handle the output differently, by passing a function as an argument (similar to the strategy pattern):
function makeDisplay(displayStrategy) {
return function(msg) {
// I'm assuming you would do some additional processing here...
displayStrategy(msg);
}
}
var display = makeDisplay(alert);
// now modify display to use document.write
display = makeDisplay(function(msg) { document.write(msg); });
Well, using eval might be a security concern but modifying a function in real-time is ok. How else you can make memoization anyway?
Although, come to think of it, changing method signature isn't a great idea, other people won't know how to call this function after this, since it would depend on execution order and it's not easy to track usually.
I have found myself needing to do this in situations where I don't have the source code for a particular piece of vendor javascript; so that could be a legitimate use case. I agree that if you have another option, it's better to do it in a more organised way, editing the original function to be more flexible.

Categories