JavaScript callback sequence of operations - javascript

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.

Related

Doubts regarding a variable scope with declaration variable via let

I've run into the strange assertion in a book in my point of view. I guess that I don't understand something but anyway it will be great if you shed light on the situation.
ajax('<host1>/items',
items => {
for (let item of items) {
ajax(`<host2>/items/${item.getId()}/info`,
dataInfo => {
ajax(`<host3>/files/${dataInfo.files}`,
processFiles);
});
}
});
An author pay attention on :
There’s another hidden problem with this code. Can you guess what it is? It occurs when you mix a synchronous artifact like a for..of imperative block invoking asynchronous functions. Loops aren’t aware that there’s latency in those calls, so they’ll always march ahead no matter what, which can cause some really unpredictable and hard-to-diagnose bugs. In these situations, you can improve matters by creating closures around your asynchronous functions, managed by using forEach() instead of the loop.
Instead of it they offer the following:
ajax('/data',
items => {
items.forEach(item => {
// process each item
});
});
Frankly speaking I expected that if we use let for loop it means we create a closure for each iteration therefore I don't see any hidden problems there.
You are correct, if the author's comment is on that exact code snippet, they were mistaken.
Loops aren’t aware that there’s latency in those calls [...] you can improve matters by [...] using forEach()
That changes nothing, forEach() is equally unaware of async calls made inside its callback as a for loop is of async calls made in its body. forEach() will "always march ahead" the same way a for loop will.
With let you cannot encounter the issue that the author seems to be worried about, as each iteration of the loop has its own item just like when using items.forEach( item => { ... .
Even with var there is no issue with that code, since the variable item is not used inside the callback to the ajax request. You could produce the author's concern by using var and using item inside the callback, such as: console.log( item.getId() );.
Note: It is important to be aware that the callbacks will most likely run in a different (seemingly random) order than they were initiated in. If you aren't aware of that it can cause surprising bugs, but that also has nothing to do with using a loop vs. forEach.
The authors of that book seem to have no clue. There is no problem of for (let … of …) that .forEach(…) would fix.
They talk about
creating closures around your asynchronous functions, managed by using forEach() instead of the loop
but the closure is not created by the forEach callback function, the closure is the callback passed into the ajax function. It closes over the surrounding scope, and there is hardly any difference between the for block scope (when using let or const) and the function body scope (when using forEach).

Javascript callback functions differences

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.

Does the use of prototyping in javascript have a negative effect on ajax calls and asynchronous code?

If I had the following object and prototyped functionality added on.
function Hello (input){
this.input = input
}
Hello.prototype.ajaxcall = function(id){
$.get("/ajax/method", {parameter:input}, function(data){
$("#"id).html(data);
});
}
Forgive the syntax if not completely correct but what it should be doing is taking in an element id, performing an ajax call and assigning the ajax call result to the innerHTML of the id. Will the fact that the ajaxcall function is shared across all instances of an object cause any problems with regards to what data will be assigned to which id if for example 20 object were all created together and had this function called immediately?
If this is the case, does it make sense to put asyncronous methods inside the object constructor instead?
What would happen if 20 objects would be created and the ajaxcall function would be called? Nothing much. The ajax calls would run asynchronously. When they have finished they are queued so that they run on the main thread when the current running operation on the main thread finished.
So the callback functions run all synchronous in a queue next time there's time for it. Nothing bad can happen here.
I don't understand your question about the constructor. What would that change? If you use your Hello objects they have an instance variable. This is is enclosed in the callback closure . Creating a new function doesn't change the value in another callback function.
If you use the same IDs the content could flash when the text changes and you don't know which callback would be ran last but that's the worst thing that could happen.
There should be no issue. You're calling the function 20 distinct times with 20 different ids.
Conceptually though. I'm not seeing why this is part of your object. The function does not use anything at all from the object itself.
This particular example would work. Your function makes no use of any instance variables, so it doesn't really make sense to declare it that way, but it makes even less sense to move it into the constructor. Still it will work because the id argument will not be shared between calls.
EDIT: So now that you've changed it so that it does use an instance variable you've got the syntax wrong, it needs to be
{parameter : this.input}
But aside from that it will still work. The asynchronous behaviour is not a problem for the code shown.

Is there a way to sequentially execute statements in Javascript?

A number of times, I have to write a callback function.
Example 1:
myTransaction.executeSql(stmt,parameters,mySuccess,myError);
Example 2: $.getScript(url [, mySuccess])
Q: Is there a way to tell JavaScript, "Please execute this line of code, and when you're done, execute the next line of code"?
I don't want to lock up the browser session, I just want it to not run the next line until it's done.
Put the call to the second function in the mySuccess handler function for the first function call. When the first one completes and runs the mySuccess function, that function will then call the second one. That is the design pattern for sequencing asynchronous operations.
You cannot write normal sequential function calls with asynchronous operations. You must use the completion functions to do your sequencing.
Here's an example using an anonymous success handler for the first function:
myTransaction.executeSql(stmt,parameters,function() {
$.getScript(url, mySuccess);
}, myError);
No there is not a way to exactly what you want. But you can use a library that helps make this less hard, like Step: https://github.com/creationix/step
Step(
function() { myTransaction.executeSql(stmt, parameters, this, myError) },
function() { $.getScript(url, this); },
function() { alert('done'); }
);
Or you will need to manually nest the callbacks.
The Javascript library Step provides a framework that encapsulates the solution suggested by #jfriend00.
You can put step 2's call in step 1's success/complete callback, as already mentioned.
Or you can look into the promise/deferred paradigm. It's a little complicated, so I won't try and explain it concisely here (and get it wrong). But given that you already seem to be using jQuery you can probably use its implementation of the deferred object. Here are a couple of articles you can read (though there are plenty more that you'll find with Google):
http://blogs.msdn.com/b/ie/archive/2011/09/11/asynchronous-programming-in-javascript-with-promises.aspx
http://joseoncode.com/2011/09/26/a-walkthrough-jquery-deferred-and-promise/
http://www.infoq.com/articles/surviving-asynchronous-programming-in-javascript
Frame.js is another library, similar to Step, that solves this problem eloquently and provides a host of advantages over setTimeouts or nested callbacks.

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

Categories