making asynchronous calls with jquery - javascript

I have a function called checkStatus(x) where x is Id. How can I call this function n times asynchronously ? Without being dependent one on another to completed and for another to start?
I'm using jquery
EDIT:
I'm not sure if I used the correct term, but here is what I want. I have a list of ID's and I iterate trough a list, I want to execute this function for each ID.
But I don't want to wait for one id to finnish, and then to execute this function on another id. Is it possible to execute this function at the same time?

Javascript engines are single-threaded, meaning that only one piece of code is ever executing at once. Asynchronous features (AJAX, timeouts/intervals) cause different blocks of code to run in sequence, not in parallel (i.e. you'll never get any use out of multiple processor cores in Javascript).
The simplest way to produce asynchronous (non-blocking) code is using setTimeout (I strongly discourage using setInterval), as others have suggested, but there is no performance benefit to doing so. This simply ensures that your browser won't "hang" during slow JS computations, by allowing the browser's other tasks (such as page repainting and user input) the opportunity to run. It won't actually increase the speed of those computations (in fact, it slightly slows them, due to the small additional overhead of the timeouts).
It is possible to create separate threads in Javascript using web workers, but their capabilities are limited (for example, they cannot alter the DOM) and they are not yet supported by IE.
An example of a long-running, non-blocking task using "recursive" setTimeout calls:
function getStarted(elements) {
// this function must be inside the outer function
// so that `i` (below) can be accessed via a closure
function processElement() {
// do work on elements[i] here
// or pass it to another function
// this continues only if we haven't hit the end of the array,
// like the second and third clauses of a `for` loop
if (++i < elements.length) {
setTimeout(processElement, 0);
}
}
// don't bother with empty arrays
if (elements.length) {
// the same `i` is used each time processElement runs
// and acts just like a `for` loop index
var i = 0;
// optional: make a copy of the array so that it
// doesn't get modified while we're working
elements = elements.slice();
// even a zero-millisecond "delay" gives the browser the
// opportunity to run other code
setTimeout(processElement, 0);
}
}

Use the setTimeout or setInterval functions.
setTimeout(function(){checkStatus(x);}, 100);
setTimeout(function(){checkStatus(x);}, 200);
setTimeout(function(){checkStatus(x);}, 300);

Related

How to "view" the canvas being drawn on live

I've not experimented with canvases before. I've made a project which involves a canvas that gets continually extended, with new rows of "data" being appended to the bottom of it.
I've got the actual rendering part working fine; the final output is what I want it to be... but my intention with the project was to be able to watch as it gets drawn on the screen. However, what instead happens is that the canvas just hangs for a few seconds, and then displays all at once. This happens in Chrome at least, I've not tested other browsers.
I'm using a loop like the following:
for(var i = 0; i < 500; i++){
addRow(data, canvas);
}
And essentially I want to view each row as it's being drawn.
Any ideas how I could do this?
Since JavaScript is single-threaded, the canvas cannot be redrawn while your loop is running.
You have to create idle moments in between the calls to addRow, so the JavaScript thread is freed to actually act on the new data. You do this by making the calls to addRow asynchronous; the easiest way to do this is to (ab)use the standard function setTimeout1.
setTimeout takes a function and executes this function asynchronously, after a given delay (if you omit the delay parameter, a delay of 0ms is assumed). I called this abusing this function earlier because you don't use the delay functionality, but I do think this is the standard way to execute code asynchronously; if not please let me know.
You can also pass an anonymous function (rather than a named one) to setTimeout, like so:
for(var i = 0; i < 500; i++){
setTimeout(function() {
data = calculateNextRow(data)
addRow(data, canvas);
});
}
If you need to use i inside the anonymous function, there will be some scope issues which are to complicated to explain here, but this answer does an excellent job of the deeper causes of the issues I alluded to and examples 3 and 5 illustrate exactly these issues.
1: in my earlier comment I suggested setInterval which was a mistake; setInterval calls the passed function repeatedly which is redundant since you would be calling it from a loop. Otherwise setTimeout and setInterval are very similar.

How to do a loop in Javascript that doesn't block the UI? [duplicate]

This question already has answers here:
Best way to iterate over an array without blocking the UI
(4 answers)
Closed 8 years ago.
I have some javascript on my page that takes a very long time to execute (between 10-30 seconds)
The code basically look like that :
//Iterate over all the elements in the array
for(int i=0; i<array.length; i++){
//Complex stuff for each element
}
The problem is that while this code is executing, the UI is not responsive.
Is there any way to solve this issue? I know javascript has some sort of asynchrony but I never really used it before...
Also, the order the elements are processed must always be the order that they appear in the array.
EDIT : I tried the solution below with setTimeout() and in the "duplicate", but it still doesn't fix my problem. I guess it's because the size of my array is not very big BUT the calculation for each element is pretty big.
Also the UI I want to be responsive is an animated loading gif. Since the calculation for each item is too big, the animation is sloppy.
Create a variable and set it to the starting value for your counter.
Create a function that:
Does whatever the body of the loop does
Increments the counter
Tests to see if the counter is still under the length and, if it is, calls the function again
At this point you will have functionality equivalent to what you have already.
To pause between each call of the function, and allow time for other functions to fire, replace the direct call to the function with a call to setTimeout and use the function as the first argument.
var counter = 0;
function iterator () {
//Complex stuff for each element
counter++;
if (counter < array.length) {
setTimeout(iterator, 5);
}
}
Javascript uses something called the "Event Loop". Basically, there is a single thread that executes the code for each event as it occurs.
There is a function called setTimeout that you can use to make your Javascript code run in a future iteration of the loop. One trick that some developers use to keep the UI responsive during a long-running Javascript task is to periodically invoke code to be run with a timeout of zero. This cause the code to execute almost immediately without locking the event loop.
For example, you could write
var i = 0;
setTimeout(myFunction, 0);
function myFunction() {
// complex stuff for each element.
i++;
if (i < array.length)
setTimeout(myFunction, 0);
}
Be aware that on modern browsers, as long as Javascript code is executing, the UI will be unresponsive. Some browsers will even pop up a message urging the user to kill the script; very bad!
Also, in modern browsers, there is a new feature called "Web Workers". Web Workers allow for Javascript code to be executed in a separate thread. You can create as many threads as you like, so consider using web workers as well if your task is easily parallelizable.
If you need the browser to update the page in the middle of your JS code, you need to yield to the browser, e.g. with a setTimeout, in a continuation passing style:
function doStuff(i) {
// do some stuff with index i
if (i < array.length) {
setTimeout(doStuff.bind(window, i + 1), 0);
}
}
doStuff(0);
I tend to do this kind of thing like so:
function doStuff(arr) {
if (arr.length === 0) {
// do whatever you need to do when you're done
return;
}
// Do body of computation here
// Or use setTimeout if your browser doesn't do setImmediate
setImmediate(function () { doStuff(arr.slice(1)); });
}
doStuff(actualArrayOfThings);
Basically, break your loop body up, and use recursion to run each part of the loop in order. It's pretty easy to break this out into a helper function, since the loop body itself is what varies. Something like:
function eachAsync(arr, body) {
if (arr.length === 0) {
// do whatever you need to do when you're done
return;
}
body(arr[0]);
setImmediate(function () { eachAsync(arr.slice(1), body); });
}
eachAsync(actualArrayOfThings, doStuff);
If your task is to process data without interfering with the user interface you can use WebWorkers
https://developer.mozilla.org/en/docs/Web/Guide/Performance/Using_web_workers
Note it's supported by modern browsers.
Use setTimeOut() if the for loop is doing some tidy work. It depends upon the complex stuff executing for each iteration.
Also, consider using JQuery/AJAX for executing it asynchronously.

Can I use setTimeout to create a cheap infinite loop?

var recurse = function(steps, data, delay) {
if(steps == 0) {
console.log(data.length)
} else {
setTimeout(function(){
recurse(steps - 1, data, delay);
}, delay);
}
};
var myData = "abc";
recurse(8000, myData, 1);
What troubles me with this code is that I'm passing a string on 8000 times. Does this result in any kind of memory problem?
Also, If I run this code with node.js, it prints immediately, which is not what I would expect.
If you're worried about the string being copied 8,000 times, don't be, there's only one copy of the string; what gets passed around is a reference.
The bigger question is whether the object created when you call a function (called the "variable binding object" of the "execution context") is retained, because you're creating a closure, and which has a reference to the variable object for the context and thus keeps it in memory as long as the closure is still referenced somewhere.
And the answer is: Yes, but only until the timer fires, because once it does nothing is referencing the closure anymore and so the garbage collector can reclaim them both. So you won't have 8,000 of them outstanding, just one or two. Of course, when and how the GC runs is up to the implementation.
Curiously, just earlier today we had another question on a very similar topic; see my answer there as well.
It prints immediately because the program executes "immediately". On my Intel i5 machine, the whole operation takes 0.07s, according to time node test.js.
For the memory problems, and wether this is a "cheap infinite loop", you'll just have to experiment and measure.
If you want to create an asynchronous loop in node, you could use process.nextTick. It will be faster than setTimeout(func, 1).
In general Javascript does not support tail call optimization, so writing recursive code normally runs the risk of causing a stack overflow. If you use setTimeout like this, it effectively resets the call stack, so stack overflow is no longer a problem.
Performance will be the problem though, as each call to setTimeout generally takes a fair bit of time (around 10 ms), even if you set delay to 0.
The '1' is 1 millisecond. It might as well be a for loop. 1 second is 1000. I recently wrote something similar checking on the progress of a batch of processes on the back end and set a delay of 500. Older browsers wouldn't see any real difference between 1 and about 15ms if I remember correctly. I think V8 might actually process faster than that.
I don't think garbage collection will be happening to any of the functions until the last iteration is complete but these newer generations of JS JIT compilers are a lot smarter than the ones I know more about so it's possible they'll see that nothing is really going on after the timeout and pull those params from memory.
Regardless, even if memory is reserved for every instance of those parameters, it would take a lot more than 8000 iterations to cause a problem.
One way to safeguard against potential problems with more memory intensive parameters is if you pass in an object with the params you want. Then I believe the params will just be a reference to a set place in memory.
So something like:
var recurseParams ={ steps:8000, data:"abc", delay:100 } //outside of the function
//define the function
recurse(recurseParams);
//Then inside the function reference like this:
recurseParams.steps--

Javascript Anonymous Functions and Global Variables

I thought I would try and be clever and create a Wait function of my own (I realise there are other ways to do this). So I wrote:
var interval_id;
var countdowntimer = 0;
function Wait(wait_interval) {
countdowntimer = wait_interval;
interval_id = setInterval(function() {
--countdowntimer <=0 ? clearInterval(interval_id) : null;
}, 1000);
do {} while (countdowntimer >= 0);
}
// Wait a bit: 5 secs
Wait(5);
This all works, except for the infinite looping. Upon inspection, if I take the While loop out, the anonymous function is entered 5 times, as expected. So clearly the global variable countdowntimer is decremented.
However, if I check the value of countdowntimer, in the While loop, it never goes down. This is despite the fact that the anonymous function is being called whilst in the While loop!
Clearly, somehow, there are two values of countdowntimer floating around, but why?
EDIT
Ok, so I understand (now) that Javascript is single threaded. And that - sort of - answers my question. But, at which point in the processing of this single thread, does the so called asynchronous call using setInterval actually happen? Is it just between function calls? Surely not, what about functions that take a long time to execute?
There aren't two copies of the variable lying around. Javascript in web browsers is single threaded (unless you use the new web workers stuff). So the anonymous function never has the chance to run, because Wait is tying up the interpreter.
You can't use a busy-wait functions in browser-based Javascript; nothing else will ever happen (and they're a bad idea in most other environments, even where they're possible). You have to use callbacks instead. Here's a minimalist reworking of that:
var interval_id;
var countdowntimer = 0;
function Wait(wait_interval, callback) {
countdowntimer = wait_interval;
interval_id = setInterval(function() {
if (--countdowntimer <=0) {
clearInterval(interval_id);
interval_id = 0;
callback();
}
}, 1000);
}
// Wait a bit: 5 secs
Wait(5, function() {
alert("Done waiting");
});
// Any code here happens immediately, it doesn't wait for the callback
Edit Answering your follow-up:
But, at which point in the processing of this single thread, does the so called asynchronous call using setInterval actually happen? Is it just between function calls? Surely not, what about functions that take a long time to execute?
Pretty much, yeah — and so it's important that functions not be long-running. (Technically it's not even between function calls, in that if you have a function that calls three other functions, the interpreter can't do anything else while that (outer) function is running.) The interpreter essentially maintains a queue of functions it needs to execute. It starts starts by executing any global code (rather like a big function call). Then, when things happen (user input events, the time to call a callback scheduled via setTimeout is reached, etc.), the interpreter pushes the calls it needs to make onto the queue. It always processes the call at the front of the queue, and so things can stack up (like your setInterval calls, although setInterval is a bit special — it won't queue a subsequent callback if a previous one is still sitting in the queue waiting to be processed). So think in terms of when your code gets control and when it releases control (e.g., by returning). The interpreter can only do other things after you release control and before it gives it back to you again. And again, on some browsers (IE, for instance), that same thread is also used for painting the UI and such, so DOM insertions (for instance) won't show up until you release control back to the browser so it can get on with doing its painting.
When Javascript in web browsers, you really need to take an event-driven approach to designing and coding your solutions. The classic example is prompting the user for information. In a non-event-driven world, you could do this:
// Non-functional non-event-driven pseudo-example
askTheQuestion();
answer = readTheAnswer(); // Script pauses here
doSomethingWithAnswer(answer); // This doesn't happen until we have an answer
doSomethingElse();
That doesn't work in an event-driven world. Instead, you do this:
askTheQuestion();
setCallbackForQuestionAnsweredEvent(doSomethingWithAnswer);
// If we had code here, it would happen *immediately*,
// it wouldn't wait for the answer
So for instance, askTheQuestion might overlay a div on the page with fields prompting the user for various pieces of information with an "OK" button for them to click when they're done. setCallbackForQuestionAnswered would really be hooking the click event on the "OK" button. doSomethingWithAnswer would collect the information from the fields, remove or hide the div, and do something with the info.
Most Javascript implementation are single threaded, so when it is executing the while loop, it doesn't let anything else execute, so the interval never runs while the while is running, thus making an infinite loop.
There are many similar attempts to create a sleep/wait/pause function in javascript, but since most implementations are single threaded, it simply doesn't let you do anything else while sleeping(!).
The alternative way to make a delay is to write timeouts. They can postpone an execution of a chunk of code, but you have to break it in many functions. You can always inline functions so it makes it easier to follow (and to share variables within the same execution context).
There are also some libraries that adds some syntatic suggar to javascript making this more readable.
EDIT:
There's an excelent blog post by John Resig himself about How javascript timers work. He pretty much explains it in details. Hope it helps.
Actually, its pretty much guaranteed that the interval function will never run while the loop does as javascript is single-threaded.
There is a reason why no-one has made Wait before (and so many have tried); it simply cannot be done.
You will have to resort to braking up your function into bits and schedule these using setTimeout or setInterval.
//first part
...
setTimeout(function(){
//next part
}, 5000/*ms*/);
Depending on your needs this could (should) be implemented as a state machine.
Instead of using a global countdowntimer variable, why not just change the millisecond attribute on setInterval instead? Something like:
var waitId;
function Wait(waitSeconds)
{
waitId= setInterval(function(){clearInterval(waitId);}, waitSeconds * 1000);
}

JavaScript asynchronous race condition

There is array of objects, which are expanded with parallel ajax requests. When last request is done array should be processed. The only solution i see is:
function expandArray(objects, callback){
number_of_requests=objects.length-1;
for(i in objects){
$.getJSON(request,function(){
//expanding array
if(--number_of_reuests==0){
callback();
}
});
}
}
But as requests are executed in parallel there is chance of race condition. Variable number_of_requests can be edited by two "threads" simultaneously. How to avoid chance of race condition?
Is it possible to rework your AJAX so that it all goes in one request? That part of the system will be the biggest bottleneck and can get tricky (as you've found out), so the less requests you make, the better.
The only other way I could think would be if each request mutated its related object, setting a flag value or something, and then you looped through all the objects to check if all the flags had been set yet.
Isn't Javascript single threaded? The kind of condition you talk of wouldn't occur.
It's more complex, but I would suggest using a third function to monitor the results. Something like this:
1) Start monitor - using an appropriate interval monitor (using an interval to test here is important - a simple loop would lock the JS engine up tight) the results of requests A and B.
2) Call request A.
3) Call request B.
4) Request B finishes - callback function sets a "B All Done!" value.
5) Request A finishes - callback function sets an "A All Done!" value.
6) Monitor recognizes that both requests are completed and calls function which uses data from both.
Worded more simply this is "dependencies" (multiple calls)to "monitor" (the function that checks dependencies) to "completion" (the action to take when all is ready).
You can create the callbacks and the completion function as nested functions to maintain encapsulation and reduce "little" in the global scope.
You can extend your dependencies as far as you like.

Categories