timer = window.setTimeout(function () {
//do something
window.setTimeout(arguments.callee, 1000);
}, 1000);
the result is that these codes work well.
but why doesn't it cause the error below?
Maximum Call Stack Size Exceeded
when debugging it, find the variable scope don't include the scope of previous executed "setTimeout function"
Who can explain this?
with documentation preferably.
setTimeout is asynchronous (it returns before executing the callback), and the callback will be executed on a new, empty stack frame. That's the whole purpose. It will never overflow the stack.
It is not a recursive call, for which scope (in case of a non-tail-call-optimized function) would need to be retained. But that would also mean that the function became blocking, which is not what you want.
This is because the Timeout callbacks are not stored in the stack as you are assuming: there are in a queue, waiting to be executed in its own stack. And in your code the queue is filled when the previous execution is completed, so the queue is not growing.
UPDATE: You can check the specs here, but I'm copying the text:
The setTimeout() method must run the following steps:
Let handle be a user-agent-defined integer that is greater than zero
that will identify the timeout to be set by this call.
Add an entry to the list of active timeouts for handle.
Get the timed task handle in the list of active timeouts, and let
task be the result.
Get the timeout, and let timeout be the result.
If the currently running task is a task that was created by the
setTimeout() method, and timeout is less than 4, then increase
timeout to 4.
Return handle, and then continue running this algorithm
asynchronously.
If the method context is a Window object, wait until the Document
associated with the method context has been fully active for a
further timeout milliseconds (not necessarily consecutively).
Otherwise, if the method context is a WorkerUtils object, wait until
timeout milliseconds have passed with the worker not suspended (not
necessarily consecutively).
Otherwise, act as described in the specification that defines that
the WindowTimers interface is implemented by some other object.
Wait until any invocations of this algorithm started before this one
whose timeout is equal to or less than this one's have completed.
Optionally, wait a further user-agent defined length of time.
Related
I'm seeing this behavior in Node and Chrome:
setTimeout(()=>{ console.log('timeout') }, 0)
Promise.resolve().then(()=>{ console.log('promise') })
console.log('sync')
// output order:
// sync
// promise
// timeout
My question is, is this consistent behavior? I.e, according to spec, does a then or await on a memoized/already resolved promise always fire before setTimeout(fn, 0)?
I want to use this in something like the following, returning one thing if I have a memoized result in my promise and another if not:
// somewhere during object initialization
this.resultingPromise = expensiveAsyncFunction()
// in a method called frequently
Promise.race([
new Promise(resolve => setTimeout(() => resolve('default'), 0)),
this.resultingPromise
])
Promise.resolve will schedule a microtask while setTimeout schedule a macrotask. And the microtasks will run before running the next macrotask.
More information about event loop in general: https://www.youtube.com/watch?v=8aGhZQkoFbQ
More technical details about events loop: https://www.youtube.com/watch?v=cCOL7MC4Pl0
so you have 2 async waiting States, but notice that one of them is constant and one is changing (variable). The timeout is set in an XML variable aside while the promise could took forever. If I understood your question quite well, when you have something you rely on take too long and something too short, unless you have a constant applied on one of them like the timeout, then one might end up running shorter unexpectedly (!) Be prepared for that and instead use monolithic structure from code security reasons and not performance.
There's no guarantee that one will be before the other. If you want to guarantee the order of execution - use Promises.
From my understanding Promise has a higher priority in the call stack than setTimeout, and of course synchronous code block will be the first to be executed. In that case, yes the observed behaviour above (in the order of synchronous code block, promise.resolve, and setTimeout 0) should be consistent.
I'm tying to call two functions in JavaScript when a button click event happens.
<button type="submit" id="mySubmit" onClick="submitInput();getAll()">Search</button>
So I wondered what function will call first. And I have no idea.
Will the submitInput() executes first or getAll() or both executes at the same time concurrently. ?
It executes the same way as ordinary javascript. submitInput() executes first. I would not reccomend doing it this way though. It would be considered bad practice. keep your javascript out of your HTML ok.
Lastly, just because something executes first, does not mean that it will finish first.. javascript is both async and synchronous in some cases.
JavaScript is by nature mono-thread, that is to say its engine can only compute one operation at once (it is not parallel !). It means that as long as a process is not finished, the user remains stuck in front of his browser and has to wait till the end. Theoritically :)
Fortunately, JS is also asynchronous, it means that one is able to free the user thread, waiting for some other conditions to be fullfilled to continue the computation. To be more accurate, the execution of some functions can be delayed, one of the simplest examples is the use of the functions setTimeout() (once) or setInterval() (several times). A callback is a function triggered only under some conditions (i.e. a time interval expires, a script sends an answer, etc...). It prevents the browser from being "freezed", waiting for the result of a computation.
In your case, if there isn't any asynchronous call, the functions will be executed in the order you gave. Once the first is completed, the second will be triggered.
Try those two dummy functions :
function myFunction() {
for (var iter = 0; iter < 500000000; iter++) {
if (iter==499999999) {alert ("done !");}
}
}
function myFunction2() {
alert ("Hi there !");
}
Call them in this order, then change their order. The second will always be executed once the first is complete.
I am trying to write a Windows app. I am curious to know what happens when you pass WinJS.Promise.Timeout() undefined value rather than a numerical milliseconds value. Will it be equivalent to passing the function a value of 0, or the behavior is unpredictable?
According to the code the setImmidiate function is called when this value is not specified. This means the promise is fulfilled when the current task is completed.
When you pass 0 a JavaScript setTimeout function is used internally. This function is limited to 250 calls per second on some systems. When passing 'undefined' to WinJS.Promise.Timeout() it doesn't use a setTimeOut call. So it could be a bit faster in some cases.
You can find more info on the setImmidate function on MSDN.
As Sorskoot explains, the code makes it clear that setImmediate is called if the interval is zero or undefined. The docs (http://msdn.microsoft.com/en-us/library/windows/apps/xaml/br229729.aspx) state this clearly:
timeout
Type: Number
The timeout period in milliseconds. If this value is zero or not specified, msSetImmediate is called, otherwise setTimeout is called.
It's really just saying that a zero or undefined timeout should just yield the UI thread and then complete.
The thing I don't understand about closures is the fact that the setTimeout callbacks don't fire until the loop has finished. It looks to me that clearly the function is being executed during each iteration.
I am not concerned why they are all "6"'s I understand that part. I just need an explanation as to why it waits till the loop has to finish before they actually run.
for (var i = 1; i <= 5; i++)
{
setTimeout(function timer()
{
console.log(i);
}, 0);
}
The setTimeouts are queued to start running at the end of the current event loop. So, the setTimeouts can fire much later than the end of the for loop.
MDN has a great description about the event loop with regard to setTimeout:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/EventLoop
Specifically this part:
Calling setTimeout will add a message to the queue after the time
passed as second argument. If there is no other message in the queue,
the message is processed right away; however, if there are messages,
the setTimeout message will have to wait for other messages to be
processed. For that reason the second argument indicates a minimum
time and not a guaranteed time.
JavaScript runs with a single event loop.
The event loop is busy running the function that is calling setTimeout so it isn't looking to see if any events are on the timeout queue waiting to run.
Even if that wasn't the case, most JS implementations implement a minimum timeout (see Minimum delay and timeout nesting) value and raise whatever you pass (0) to it if it falls below that value.
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);
}