If multiple callbacks are registered at the same time, is it guaranteed that the first callback to be called will be the one with the least delay?
Consider the following code:
function foo(i) {
setTimeout(function () {
console.log(i);
}, i);
}
for (var i = 0; i < 1000; i++) {
foo(i);
}
Is this code guaranteed to output 1-1000 in order?
Please note: This question is not about using equal delays. It has been established that multiple setTimeout() calls with equal delays are not guaranteed to execute in order.
Yes!!
function foo(i) {
setTimeout(function () {
console.log(i);
}, i);
}
for (var i = 1; i <= 1000; i++) {
foo(i);
}
Explanation :
As you are Calling setTimeout it will execute independently doesn't matter how much setTimeout are running or will run,So its dependent on time you call and timing you set.Hope you get this.
I know many of the people have already answered this question. But, most of the people don't know exactly how the event loop works. Even I got it recently. So, I thought it would be helpful to all whoever gets to this post.
setTimeout() function works in accordance with the event callback and render queue. Rendering queue is the reason why it is not guaranteed that your callback would execute after the exact timeout. There are concepts like
call stack,
web apis and
callback queue
You have this below function called multiple times,
function foo(i) {
setTimeout(function () {
console.log(i);
}, i);
}
so the flow would be something like, each call to foo(i) would first go to call stack. Once the call stack reaches to its top (when loop is over), one by one the web api(browser specific)would handle the poped out function from the stack and then it moves to the callback queue when the timeout has reached. Depending on the availability that is, if rendering is not happening, the callback gets executed.
Inside the callback queue the functions are lined up in the order of calling.
So, the order is guaranteed.
A better place to understand the event queue is the below article.
Philip Roberts: What the heck is the event loop?
Related
I am new to JavaScript! I am trying to make an extremely naive blocking statement in a JavaScript program. I think JavaScript is single threaded (mostly, except for things like setTimeout), and synchronous within a code block, so I expected that I could block execution of my code with a while loop. I do not want to use setTimeout because I'm not sure it will be reliably precise enough to do what I want.
Let me explain. I have a button with class="playback", which should trigger a series of sounds to play. The callback makes an AJAX request, and then hands data to playbackRecording(). This function accepts a list of objects which have two attributes: key_pressed (helps determines which sound to play, but is not important for this issue), and time_to_next_key (how many milliseconds to wait until the next sound is played). actionApp() is the function that causes the sound to actually get played.
My expectation: The first sound is played. Then a short amount of time passes and the next action happens. Repeat until finished.
What actually happens: An amount of time elapses that equals the sum of time_to_next_key for all keypresses, then all the sounds are played at the end.
function playbackRecording(content) {
var waitTime = 0;
var keypress = content[0];
actionApp(keypress.key_pressed);
for (var i = 1; i < content.length; i++) {
waitTime += keypress.time_to_next_key;
keypress = content[i];
var end = Date.now() + waitTime;
while(Date.now() < end) {}
actionApp(keypress.key_pressed);
}
}
function playbackLinkClicked(evt) {
var urlString = '/fetch_recording/' + this.id;
$.get(urlString, function(data){
if (data.status === 'success') {
playbackRecording(data.content);
} else {
alert('Could not load recording.');
}
});
}
$('.playback').click(playbackLinkClicked);
What I am missing?
Playing the sound is done by asynchronous code (I don't know exactly what actionApp() does, but the behavior you describe is consistent with this, and it's how most interactive code works in Javascript). So when you call actionApp(), it's putting this code on the event queue. It will not actually play anything until Javascript returns to the main event loop.
The while loop is synchronous, so your code doesn't return until all of them are finished. Each time it calls actionApp() it adds another sound to the event queue. Then when it finishes, all the queued actions get executed.
I was reading an article that stated that to create a nonblocking/asynchronous function, usage of setTimeout is crucial. And I thought that the function that is passed to setTimeout runs in the background. Then I read in another article that setTimeout does block the event loop when function is fired. So, I tried the following function to test.
function getit(cb) {
var i = 0;
setTimeout(function() {
while (i < 200000) { i++; console.log(i); }
cb(i);
} , 1000);
console.log(i);
}
getit(function(message) { console.log(message); });
Apparently, when 1000ms passes and it is time to execute the function, the thread is blocked and my browser freezes. My question is, if asynchronous code is not supposed to block the thread, how is that possible when the function is being executed when time elapses and not in the background? It seems like this is just a delay, but eventually, the function is going to be executed line by line and block the loop anyway. Is there something I'm missing or confused about?
Node.js execution model can be represented by the following code:
function main() {
while(running) {
var timerCb = getNextTimedoutCallback();
if( timerCb ) timerCb(); // execute it
var ioCb = getNextCompleteIOOperationCallback();
if( ioCb ) ioCb(); // execute it
}
}
Everything runs in single thread. IO operations run in worker threads and populate internal queue of completed IO operations. That getNextCompleteIOOperationCallback(); just pulls completed operation from the queue.
In the same way setTimeout() simply pushes function alongside with its end time to the timers queue (ordered by end time). And getNextTimedoutCallback() pulls next expired timeout (if any).
As you see either timer function or IO callback can block the whole thing.
That's known as cooperative multitasking.
You first have to understand that JavaScript, under most contexts is single-threaded. Be it asynchronous or not, once your script start executing, it blocks everything.
Your example above therefore enters the busy while-loop after 1000ms and begin blocking other execution.
To overcome this, the busy block has to be broken down to "yield" (Java terminology) execution cycles for other tasks.
E.g.:
function getit(cb) {
setTimeout(function() {
lessBlockingGetIt(cb);
} , 1000);
}
// Note that this is only less blocking, and much slower
function lessBlockingGetIt(cb) {
// Instead of directly looping, we batch-loop with a setTimeout
var numberOfTimes = 1000; // Reduced the size so it doesn't block like forever
var batchSize = 10;
function executeBatch(start) {
// We use a zero-timeout function is achieve a "yield" behavior so other tasks in the event loop can execute
setTimeout(function(){
var i = start, j;
for(j = 0; i < numberOfTimes && j < batchSize; i++, j++){
console.log(i);
}
if(i < numberOfTimes){
executeBatch(i);
} else {
cb(i);
console.log(i);
}
}, 0);
}
// Start the recursion loop
executeBatch(0);
}
getit(function(message) { console.log(message); });
However, you would notice the execution is much slower, and the browser is apparently less responsive than otherwise true multithreading.
To achieve real multithreading, you would need to use web workers http://www.w3schools.com/html/html5_webworkers.asp
Let's assume I have the following code:
var funcIsRunning = 0;
function a(){
funcIsRunning = 1;
// some code ... (maybe lots of code);
funcIsRunning = 0;
}
Is there any chance that some asynchronous function will catch funcIsRunning flag in '1' position? (e.g. the callback of XHR or a function that is called via setTimeout, etc.)
Or, which is the same, can two functions be executed at the same time (not one after another)?
Just to make it clear... In fact, I don't have to run 2 funcs simultaneously... I'm just wondering how it works.
P.S. I would be very grateful if you could provide documentation/grounding of your answer
Thanks a lot!
Made a test here that illustrates given answers: http://jsfiddle.net/rz7tvyof/
No, JavaScript is single threaded and runs only one function at a time. Although, if you have a callback function waiting for, say, a network request that happens to return at funcIsRunning = 1, that callback function will be put on the queue that is handled by the event loop
JavaScript event loop explained
Normally no thanks to event loop. But you can use Web Workers to run code in parallel (with some limitations such as access to DOM etc.).
Worker documentation
What is the difference between those two, and when will I use one over the other?
setTimeout is simply like calling the function after delay has finished. Whenever a function is called it is not executed immediately, but queued so that it is executed after all the executing and currently queued eventhandlers finish first. setTimeout(,0) essentially means execute after all current functions in the present queue get executed. No guarantees can be made about how long it could take.
setImmediate is similar in this regard except that it doesn't use queue of functions. It checks queue of I/O eventhandlers. If all I/O events in the current snapshot are processed, it executes the callback. It queues them immediately after the last I/O handler somewhat like process.nextTick. So it is faster.
Also (setTimeout,0) will be slow because it will check the timer at least once before executing. At times it can be twice as slow. Here is a benchmark.
var Suite = require('benchmark').Suite
var fs = require('fs')
var suite = new Suite
suite.add('deffered.resolve()', function(deferred) {
deferred.resolve()
}, {defer: true})
suite.add('setImmediate()', function(deferred) {
setImmediate(function() {
deferred.resolve()
})
}, {defer: true})
suite.add('setTimeout(,0)', function(deferred) {
setTimeout(function() {
deferred.resolve()
},0)
}, {defer: true})
suite
.on('cycle', function(event) {
console.log(String(event.target));
})
.on('complete', function() {
console.log('Fastest is ' + this.filter('fastest').pluck('name'));
})
.run({async: true})
Output
deffered.resolve() x 993 ops/sec ±0.67% (22 runs sampled)
setImmediate() x 914 ops/sec ±2.48% (57 runs sampled)
setTimeout(,0) x 445 ops/sec ±2.79% (82 runs sampled)
First one gives idea of fastest possible calls. You can check yourself if setTimeout gets called half as many times as other. Also remember setImmediate will adjust to your filesystem calls. So under load it will perform less. I don't think setTimeout can do better.
setTimeout is un-intrusive way of calling functions after some time. Its just like its in the browser. It may not be suited for server-side (think why I used benchmark.js not setTimeout).
A great article about how event loop works and clears some misconceptions.
http://voidcanvas.com/setimmediate-vs-nexttick-vs-settimeout/
Citing the article:
setImmediate callbacks are called after I/O Queue callbacks are finished or timed out. setImmediate callbacks are placed in Check Queue, which are processed after I/O Queue.
setTimeout(fn, 0) callbacks are placed in Timer Queue and will be called after I/O callbacks as well as Check Queue callbacks. As event loop, process the timer queue first in each iteration, so which one will be executed first depends on which phase event loop is.
setImmediate() is to schedule the immediate execution of callback after I/O events callbacks and before setTimeout and setInterval .
setTimeout() is to schedule execution of a one-time callback after delay milliseconds.
This is what the documents say.
setTimeout(function() {
console.log('setTimeout')
}, 0)
setImmediate(function() {
console.log('setImmediate')
})
If you run the above code, the result will be like this... even though the current doc states that "To schedule the "immediate" execution of callback after I/O events callbacks and before setTimeout and setInterval." ..
Result..
setTimeout
setImmediate
If you wrap your example in another timer, it always prints setImmediate followed by setTimeout.
setTimeout(function() {
setTimeout(function() {
console.log('setTimeout')
}, 0);
setImmediate(function() {
console.log('setImmediate')
});
}, 10);
always use setImmediate, unless you are really sure that you need setTimeout(,0) (but I can't even imagine, what for). setImmediate callback will almost always be executed before setTimeout(,0), except when called in first tick and in setImmediate callback.
I think the answer of Navya S is not correct, here is my test code:
let set = new Set();
function orderTest() {
let seq = [];
let add = () => set.add(seq.join());
setTimeout(function () {
setTimeout(function () {
seq.push('setTimeout');
if (seq.length === 2) add();
}, 0);
setImmediate(function () {
seq.push('setImmediate');
if (seq.length === 2) add();
});
}, 10);
}
// loop 100 times
for (let i = 0; i < 100; i++) {
orderTest();
}
setTimeout(() => {
// will print one or two items, it's random
for (item of set) {
console.log(item);
}
}, 100);
The explanations is here
setTimeout(fn,0) can be used for preventing the browser from freezing in massive update. for example in websocket.onmessage, you may have html changes, and if messages keep coming, the browser may freeze when using setImmidiate
To understand them deeply please once go through the event loop phases.
SetImmediate:
It gets executed in the "check" phase. The check phase is called after the I/O phase.
SetTimeOut:
It gets executed in the "timer" phase. The timer phase is the first phase but is called after the I/O phase as well as the Check phase.
To get the output in a deterministic manner, it will depend on which phase the event-loop is; accordingly, we can use the function out of two.
When the Javascript engine starts execution, It checks code line by line.
setTimeout(function() {
console.log('setTimeout')
}, 0)
setImmediate(function() {
console.log('setImmediate')
})
When it comes to
settimeout, it moves from call-stack to call queue and starts a timer for execution.
setimmediate, it moves from call-stack to macro-queue(which is start execution immediately after the first loop is complete)
So, if settimeout value is 0, it will complete its timer before call-stack loop complete.
that's why, settimeout will print before setimmediate.
Now, suppose
setTimeout(function() {
setTimeout(function() {
console.log('setTimeout')
}, 0);
setImmediate(function() {
console.log('setImmediate')
});
}, 10);
This means, first main timeout move to call-queue. meanwhile, call-stack complete its execution.
So, after 10ms, function comes to call stack, it will direct execute setimmediate. Because call-stack is already free to execute task.
use setImmediate() for not blocking the event loop. The callback will run on the next event loop, as soon as the current one is done.
use setTimeout() for controlled delays. The function will run after the specified delay. The minimum delay is 1 millisecond.
This question already has answers here:
Why is setTimeout(fn, 0) sometimes useful?
(19 answers)
Closed 9 years ago.
I have problem when using jQuery plugin tablesorter and I can't call trigger twice.
For example this won't work:
this._$table.trigger('update');
this._$table.trigger('sorton', [[[1,1]]]);
But this works:
this._$table.trigger('update');
setTimeout($.proxy(function() {
this._$table.trigger('sorton', [[[1,1]]]);
}, this), 1);
And then I see that problem was in trigger 'update', it call method with body:
function () {
var me = this;
setTimeout(function () {
// rebuild parsers.
me.config.parsers = buildParserCache(
me, $headers);
// rebuild the cache map
cache = buildCache(me);
}, 1);
}
Why did the tablesorter developer use setTimeout with one millisecond?
Short asnwer: Function execution queueing
This is the short answer to your question. setTimeout with either 0 or 1 millisecond is used for function execution queueing. Read on to find out why and how.
Javascript has single threaded execution
Javascript engine is a single threaded process. So whenever developers wanted to defer some function execution to get executed right after the current one that's just being executed, a setTimeout is being used to actually queue the next function... It doesn't have anything to do directly with events although functions may be event handlers. The only event in this equation is the timeout event that setTimeout creates.
This is an example of two functions where the first function during its execution queues a second function to be executed right after it.
function first()
{
// does whatever it needs to
// something else needs to be executed right afterwards
setTimeout(second, 1);
// do some final processing and exit
return;
}
function second()
{
// whatever needs to be done
}
So to javascript engine thread the execution queue looks like this:
first()
second()
Mind that this has nothing to do with function call stack.
Why 1ms?
1ms is a very short amount of time, which (almost) assures that your second function will get executed right after your first function returns. You may see sometimes even 0ms which actually executes it right after first function returns.
If one would on the other hand use longer time i.e. 100ms this could result in a different function getting executed in the meantime and that could have an undesired effect on the whole UI process.
Why function queueing in the first place?
Browsers nowadays prevent client side functionality to hang current browser session by observing long running functions. If a particular function runs long enough, browser Javascript execution engine will pause it and ask the user whether they want to terminate it (kill it) or wait for it to complete.
This is usually undesired effect when you actually do have a long running function. For instance imagine you have a function that has to loop through a large number of items processing each one during the process. You definitely don't want the user to terminate the process because the loop needs to execute.
What's the solution in this case? In such case instead of having a single function with loop and executing it, you'd rather have the loop (queueing) function that would then queue function calls for processing each item. This is just an outer skeleton of such functionality.
function queueItems(items) {
for(var i = 0; i < items.length, i++)
{
setTimeout((function(item) {
return function() {
processItem(item);
};
})(items[i]), 0);
}
}
function processItem(item) {
// process individual item
}
This way you'd prevent your functions to run too long and after each executed function control would get back to Javascript engine resetting its function-hang timer. But be aware that while your functions are being executed your UI will likely be unresponsive or at most unpredictable. It may be better to queue your function with some time space in between so UI stays responsive if that's desired.
It's an old hack. If an event needs to be triggered after another event you can use setTimeout with 1ms to make sure the event is triggered after the other event.
I think that since trigger('update') internally has a setTimeout, only by setting another setTimeout you can achieve the desired order of statement execution. If you don't call 'sorton' through setTimeout it will be executed before 'update'.
On the other hand I guess 'update' uses setTimeout for preventing 'update' from being a blocking function when it may take a long time to be executed.