Javascript and timing, specifically with callbacks - javascript

I want to make sure I understand callbacks properly, and javascript timing etc. in general.
Say my code looks like this, is it guaranteed to execute in order?
SetList(); // initializes the var _list
Some.Code(_list, function(data) {
// update list
});
DoSomething(_list); // operates on _list
Update
What I am seeing is SetList calls, then DoSomething, then Some.Code.
Some.Code calls another function. so:
Some.Code(_list, function() {
//load _list from ajax request
Other.Code.WithCallback(_list, function(){....});
});
I guess to fix this, I have to add DoSomething to the inner function as another callback?

SetList(), Some.Code() and DoSomething() will execute in that order, one after the other. The anonymous function passed as the second argument to Some.Code() could be called during the execution of Some.Code() (before the function returns and DoSomething() is called) or it could be called at a later time by another function, and event handler or timer, it all depends on when you specified it to be called.
Since you're using ajax, the request to the remote server is made on a separate thread, so the executing javascript thread continues to run and call other functions until a response (or, more specifically, for the onreadystatechange event to fire). When the ready state of the ajax request changes, its readystatechange event handler is queued to be called -- meaning it will execute as soon as all currently executing scripts finish.
If you want DoSomething() to execute after the response is received via ajax, you should run it to the end of your callback function instead.

That code would execute in order:
SetList(), then Some.Code(), then function(data), then DoSomething().
JavaScript is single-threaded, and executes in order. The only way that things would happen out of sync is if you set an interval/timer within Some.Code() or function(data) that called another function.
If you had:
var i=0;
functionCall() //some long process that sets i=1;
if (i==1) { alert("In Order!"); } else { alert("Out of Order!"); }
That would alert "In Order," But if you had:
var i=0;
setTimeout(functionCall, 1000) //some long process that sets i=1;
if (i==1) { alert("In Order!"); } else { alert("Out of Order!"); }
That would execute "Out of Order," because the third line would execute before functionCall() is called.
Updated Answer
Because you are using Ajax, I'm guessing you are making an asynchronous call, which is the reason for the delay. You have a callback function, but it's still waiting to be called back, so Javascript moves on to execute the next line while it waits.
To execute in the order you want, you'll need to do this:
SetList(); // initilizes the var _list
Some.Code(_list, function(data) {
// update list
DoSomething(_list); // operates on _list
});
This way, you can ensure that DoSomething() is called when your callback method is called, and not before.

Related

How to stop a function during its execution - JavaScript

How can I stop/terminate a function which is already executed and still running? For example, I have this function:
function foo() {
setInterval(function() {
console.log("Foo Executed !");
}, 3000);
}
foo();
Now, this foo() function will run for unlimited time, when a specific event occurs, let's say a stop button has been clicked, then I want to stop this function.
In my case the function doesn't have setInterval() function. And what if the foo() function don't have the setInterval() method, but just many lines of code that get executed and I want to stop it from executing after a specific event.
Stopping a running function is a bit different than what you are actually showing for code, which is an asynchronous operation happening outside of the function that initiated it.
Running functions can only be terminated from within the function and that is done with either a return statement or by throwing an exception.
return can be called conditionally so that the function doesn't always exit at the same point. This is often the case with form validation functions - - if something is determined to be invalid, a return is encountered so that the form is not submitted. If everything is valid, the return is skipped and the form is submitted.
Here's a simple example with return:
function foo1(){
console.log("Foo started...");
if(prompt("Type 1 to terminate right now or anything else to continue...") == "1"){
return; // Function will terminate here if this is encountered
}
console.log("Foo ending..."); // This will only be run if something other than 1 was entered
}
foo1();
And, here's an example with throwing an error (not something that is usually done):
function foo(){
console.log("foo started...");
for(var i = 0; i < 5; i++){
if(i === 3) { throw "I HATE 3!"; }
console.log(i);
}
console.log("foo ended...");
}
foo();
But, with Timers and Intervals, you'll need to call clearInterval() and/or clearTimeout() to stop them. These are different because, while some function may initiate the timer or interval, the timer runs outside of the JavaScript runtime environment as a WebAPI. For these, we have to send a message to the WebAPI that we want the timer to stop counting.
You say:
Now, this foo() function will run for unlimited time, when a specific
event occurs, let's say a stop button has been clicked, then I want to
stop this function.
But foo isn't running for an unlimited time. It's run once and then terminates. Then approximately 3 seconds later, the timer calls for the anonymous function you passed to it to be run and then that function terminates and approximately 3 seconds later the anonymous function runs again and then it again terminates and so on. The function isn't running consistently, the interval timer (the WebAPI that calls for the function to be invoked) is.
And what if the foo() function don't have the setInterval() method,
but just many lines of code that get executed and I want to stop it
from executing after a specific event.
Your question seems to imply that you want to stop a function that is currently executing when another event takes place. This can't really happen in JavaScript since JavaScript is a single-threaded environment. Any event can only be raised and handled after all other code is done processing. So, there really can't ever be a scenario like the one you mention, unless we are talking about asynchronous code. Asynchronous code is code that runs outside of the JavaScript runtime. With that kind of code, you can send a message to the WebAPI that is processing that external code that you would like to cancel/abort that processing and that is what we're doing when we call clearInterval().
See below:
document.getElementById("start").addEventListener("click", startInterval);
document.getElementById("stop").addEventListener("click", stopInterval);
// You'll need a variable to store a reference to the timer
var timer = null;
function startInterval() {
// Then you initilize the variable
timer = setInterval(function() {
console.log("Foo Executed!");
}, 1500);
}
function stopInterval() {
// To cancel an interval, pass the timer to clearInterval()
clearInterval(timer);
}
<button type="button" id="start">Start</button>
<button type="button" id="stop">Stop</button>
For that use return; in the place you want to kill the process

Can a web message call back function be executed before the previous is done executing?

If you have web messages which trigger a function and the messages are coming in quickly, can the function be executed before the previous is finished?
document.addEventListener('some_message', some_func, false);
function some_func (data){
//Is the code here always executed before the next function is executed?
}
Since there's only a single Javascript thread running, only one piece of code can run at a time. So this will always execute in the same order as events are triggered, and only one at a time:
function callback_func(data) {
alert(data);
}
However, if your callback works asynchronously, i.e. yields the thread back to the browser, then it's unpredictable:
function callback_func(data) {
setTimeout(() => {
// who knows when this will be called ¯\_(ツ)_/¯
alert(data);
}, Math.random());
}
Yes, that is the way asynchronous events work in JavaScript.
You can check out this article, which explains how async-await works in modern JavaScript.

How do I set a specific order of execution when asynchronous calls are involved?

I am new(2 days!!) to the world of JavaScript and my only prior coding experience is in Java where execution of statements takes place sequentially.
I understand that or at least I've read that JavaScript is asynchronous which means that if there is a statement that takes a long time to execute, the next statement is executed without holding up the program for the first statement.
I came across callbacks(a lot actually!!) but I couldn't see how they could be used to determine the order of execution. I wrote a piece of code just to understand how it could be done and I sure could use some help.
console.log("Beginning");
function Test(callback){
setTimeout(function(callback){
console.log("Something that takes a lot of time");
},5000);
callback();
}
function tstCallBack(){
console.log("Should come last");
}
Test(tstCallBack);
What I want is for the output to display -
Beginning
Something that takes a lot of time
Should come last
But the output I am getting is -
Beginning
Should come last
Something that takes a lot of time
Is there anything I can do to get the output in the way I want it?
Let's clear some things up in what you said:
I am new(2 days!!) to the world of JavaScript and my only prior coding
experience is in Java where execution of statements takes place
sequentially. I understand that or at least I've read that JavaScript
is asynchronous which means that if there is a statement that takes a
long time to execute, the next statement is executed without holding
up the program for the first statement.
This is not how it works. A given function is either asynchronous or its synchronous by design. It has absolutely nothing to do with how long it takes to execute. You can have a very quick async function or a very long synchronous function. What determines whether the function is asynchronous or not is how it is designed. If it uses async I/O or timers or any other async infrastructure, then at least some of the execution of the function is asynchronous. That means that some of the function will finish LATER and some of the code right after this function call will execute BEFORE the async portion finishes.
I came across callbacks(a lot actually!!) but I couldn't see how they
could be used to determine the order of execution. I wrote a piece of
code just to understand how it could be done and I sure could use some
help.
Callbacks are used to notify the calling code when some asynchronous operation has completed. This can be used either to consume the result of the asynchronous operation or can be used to execute the next piece of code that wants to run in sequence after the async operation has finished.
In your code example, if you want the desired sequence, then you must call the callback inside the setTimeout() callback so that it gets called AFTER the setTimeout() called executes, thus giving you the desired sequence.
You also have to remove the callback argument to the setTimeout callback. That callback is not passed with that argument so declaring it there is just wrong. It can be accessed directly from the parent function via a closure as shown here:
console.log("Beginning");
function Test(callback){
setTimeout(function(){
console.log("Something that is asynchronous");
// call the callback here to indicate to the calling code
// that the asynchronous operation is now complete
callback();
},5000);
console.log("After Setting Timer");
}
function tstCallBack(){
console.log("Should come last");
}
Test(tstCallBack);
This will generate a sequence in the console of:
Beginning
After Setting Timer
Something that is asynchronous
Should come last
Conceptually, the Javascript engine runs a single thread and that single thread uses an event queue. So, in your function above, this is what happens.
The first console.log("Beginning"); is executed.
Test(tstCallback) is called.
As part of executing the Test() function, a timer is scheduled. This registers a timer internal to the JS engine.
The execution of code in Test() continues, console.log("After Setting Timer"); is executed and then that function finishes.
The current thread of JS execution finishes and if there is nothing else in the event queue, then the JS engine has nothing to do, but wait for the next event to occur.
Some time later (the 5 seconds that your timer is set for), the internal timer fires and it puts the timer event in the JS event queue.
Since there is no other JS executing at the moment, the timer event is pulled out of the event queue and executed. This means that the original callback that was registered for the timer is called.
As the timer callback is called, it executes the console.log("Something that is asynchronous"); line and then calls callback().
Your tstCallback function is then called and console.log("Should come last"); is executed.
The async event finishes execution and the JS engine looks to see if there are any more events in the event queue. If so, the next event is pulled out of the queue and it is run.
There are a number of very good references on how Javascript handles asynchronous operations:
How does JavaScript handle AJAX responses in the background?
How Javascript Timers Work
Do I need to be concerned with race conditions with asynchronous Javascript?
A lot of what you've said is wrong. JavaScript is sequential in the same way as Java, but asynchronous calls are made more often. If you want your callback to be called after the long thing, you must call it after the long running program. Like so -
console.log("Beginning");
function Test(callback){
setTimeout(function(callback){
console.log("Something that takes a lot of time");
callback();
},5000);
}
function tstCallBack(){
console.log("Should come last");
}
Test(tstCallBack);
I have modified your code as below to get the desired output.
console.log("Beginning");
function Test(callback){
console.log("Something that takes a lot of time");
setTimeout(callback,5000);
}
function tstCallBack(){
console.log("Should come last");
}
Test(tstCallBack);
setTimeout takes a callback function that will be executed after the specified time interval
The use of setTimeout is the asynchronous part. When the above code is executed,first the "Begining" console statement is printed and then the Test function is called passing in a function that needs to be executed asynchronously after 500ms .
Place the callback inside setTimeout and not outside as the callback will be executed first before the setTimeout does as javascript won't wait for setTimeout execution(as JS is synchronous by nature) and executes the next line and hence you won't get the desired output.
console.log("Beginning");
function Test(callback){
setTimeout(function(){
console.log("Something that takes a lot of time");
callback();
},5000);
}
function tstCallBack(){
console.log("Should come last");
}
Test(tstCallBack);
Demo

Measuring time of execution on method

Let's say we have this:
function myMethod1() {
...
}
and later in the code:
myMethod1();
alert('myMethod1() was executed!');
I need to set timeout for the alert so that it will be called after myMethod1() executes. But how do I know the value of the second parameter for the setTimeout function? How do I measure the time needed for myMethod1() to execute?
MyMethod1() has an async ajax call.
If your method performs an asynchronous task, it's common to pass a callback function like so:
function myMethod(cb)
{
// some code, such as $.ajax
$.ajax({
url: 'example.com',
complete: function() {
// we're done, notify callback
cb();
}
});
}
Then, cb is passed in like this upon execution:
myMethod(function() {
alert('method is done');
});
alert('method returned, but is still doing stuff in the background');
This is the mantra of asynchronous design; every method that performs a task in the background will have some way of notifying a callback function of its completion.
If the method is synchronous however, you could call cb() at the end of the function body, but it would be much easier to keep what you had:
myMethod();
alert('method is done');
You dont need to. The way that you have set it up, the alert will always fire after myMethod1() finishes.
you can use a time stamp, will be precise to the millisecond.
You'll need 2 vars, one to hold the start time and one for the end tume.
And to set those var, where you want to calculate. So
///EDITED version below to make it global..
put this at he top of you js code:
var ts_start;
var ts_stop;
put this where you want to START calculating the time:
ts_start =new Date().getTime();
put this where you want to STOP calculating the time:
ts_stop =new Date().getTime();
and you can alert the millesecond by making the diff bewteen them.
alert(ts_stop-ts_start);
OR shove it in a variable...

sequential functioncalls

I am communicating with a servlet that changes and saves an external file. Since this takes some time, I need some of my javascript functioncalls to happen sequentially so that the actions of one function don't interfear the actions of another function.
To do this, I wrote a 'sequential' function that takes another function that can only be called when the busyflag is set to false (i.e. when no other functioncall is handled at the same time). This is my code:
var busy = false;
function sequential(action) {
while(busy)
setTimeout(function(){sequential(action);}, 10);
busy = true;
action();
setTimeout(function(){busy = false;}, 100);
}
function test1() {sequential(function() {alert("test1");});}
function test2() {sequential(function() {alert("test2");});}
And this is the example on jsFiddle. For some reason this code this code keeps looping on the second call (when a functioncall has to wait).
while(busy)
setTimeout(function(){sequential(action);}, 10);
setTimeout does not block, it returns immediately and allows the loop to continue. Javascript is single threaded, so this loop just keeps running and prevents any other code from executing, meaning busy will never get set to false to exit the loop.
Assuming these things you are waiting on are ajax calls, you will likely want to use some sort of queue and then in the callback of the ajax call, run the next request.
I presume your javascript is making ajax calls to your server.
If you need the different calls to run one after the other, then you should get your javascript code to set up hooks to wait until it gets results back from one call before making the next request.
I recommend using a javascript toolkit like jQuery for these purposes. It makes problems like this much easier to solve. Every ajax method in jQuery accepts at least a callback that will be called when the query is complete. For jQuery.ajax() you can go
$.ajax(...).done(function() {
// This part will be run when the request is complete
});
And for .load():
$("#my_element").load(url,data,function() {
// This part will be run when the request is complete
});
I first implemented a solution like suggested by James Montagne, but after some searchin I found out that you can use the onreadystatechange property of the XMLHttprequest to set the busy-flag to true.
This code works like expected:
function sequential(action) {
if (busy) setTimeout(function(){sequential(action);}, 20);
else action();
}
function send(message){
busy = true;
var request = new XMLHttpRequest();
request.open("POST", "owlapi", true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
request.send(message);
request.onreadystatechange = function() {busy = false;};
}

Categories