First look at a piece of code:
settimeout (function () {
Alert ("a");
}, 0);
while (1);
Alert ("B");
Hopefully in Mashan you can pop up a warning box "a" to but always did not come to, and, in Firefox ran also got such a hint, and prompted you to terminate the execution of the script, in case I choose to terminate, "a" is bounced out, but "B" but can not play out:
Warning:unresponsive Script
A script on this page may is busy, or it may have stopped responding. Can stop the script now, or you can continue to the if the script would complete.
Because more than one event in the browser executes in the queue, there is no interruption in the execution of each event (such as a mouse response event, page rendering events, settimeout-defined events, and so on). The script "B" was terminated, but the logic "a" was in the event queue and was not terminated. As you can see from this example, the lazy execution of JavaScript is not accurate. But then again, why use the SetTimeout method if you want to do it right now?
The reason is simple, because I want to put the logic of this frame into the event queue.
Why are you designing a single thread?
In fact, the JavaScript core language does not contain any threading mechanism, and the client JavaScript is not explicitly defined threading mechanism, but JavaScript still strictly follow the "single-threaded" model to execute the code. Why? Many voices on the internet say it has something to do with its history, but there is a more important reason-the deadlock. Multithreaded GUI framework is particularly easy to deadlock, this article "Multithreaded Toolkits:a Failed Dream" describes the reason for this, generally speaking, GUI behavior is mostly from the more abstract top layer to the operating system level, and the event is reversed, Bubble from the bottom of the net, the result is two opposite behavior in the meeting, to the resource lock when a positive sequence, a reverse, extremely easy to appear each other waiting for the situation of starvation, and this situation to solve this problem is tantamount to "fight back a oceanic tidal force"- Recommended reading. AWT initially wanted to design multithreading, but the user is very easy to cause deadlock and competition, and finally swing still made a single thread. Whenever this event loop+ a single thread execution pattern, we can also find many, such as the JDK GUI threading model, the main thread is a "master event loop" (and then the event Dispatch thread is introduced, but this does not change the overall basic threading model), And the cocoa of the Mac system, and so on, are all such patterns.
In addition, with regard to thread or event, the pros and cons of these two typical patterns are compared in detail in the case of Threads vs. Events article:
Pseudo-Sleep method
JavaScript is not a sleep method, because it is single-threaded execution, the sleep method is meaningless. If we have to sleep, we can only implement a meaningless pseudo sleep:
function sleep (time) {
var start = new Date (). GetTime ();
while (true) {
if (new Date (). GetTime ()-Start > Time {
Break
}
}
}
But this pseudo sleep is meaningless, because this cycle will continue to consume CPU to compare time (or consume CPU to compare time is need system call, this is not possible in JavaScript), not the real, but not the response to work.
Splitting time-consuming logic
Many times we need to split the time-consuming logic and make time for other logic to execute: The following code originates from the article "Timed array processing in JavaScript", where the author first gives a framework code for splitting logic execution:
function chunk (array, process, context) {
var items = Array.concat (); Clone the array
settimeout (function () {
var item = Items.shift ();
Process.call (context, item);
if (Items.length > 0) {
settimeout (Arguments.callee, 100);
}
}, 100);
}
But he also immediately pointed out the problem, 100 milliseconds interval delay is too long, perhaps 25 milliseconds is enough, but not 0, 0 can also make this execution split into multiple events into the queue, but we need to give the UI update rendering and so on to leave some time. So he improved again:
Copyright 2009 Nicholas C. Zakas. All rights reserved.
MIT Licensed
function Timedchunk (items, process, context, callback) {
var todo = Items.concat (); Create a clone of the original
settimeout (function () {
var start = +new Date ();
do {
Process.call (Context, todo.shift ());
while (Todo.length > 0 && (+new Date ()-Start < 50));
if (Todo.length > 0) {
SetTimeout (Arguments.callee, 25);
} else {
callback (items);
}
}, 25);
}
As you can see, this allows you to use time more fully, to perform tasks in an array, to continue execution as long as it takes less than 50 milliseconds to execute within each chunk, and to leave an external event for 25 milliseconds to process once it is more than 50 milliseconds.
Web Worker
In essence, Web worker is a JavaScript that runs in the background and does not affect the performance of the page. When you execute a script in an HTML page, the state of the page is not responsive until the script is completed. Web worker is JavaScript that runs in the background, independent of other scripts, and does not affect the performance of the page. This can be seen as a HTML5 attempt to improve on single-threaded JavaScript abuses (there are a number of current problems, such as browser differences).
var w=new Worker ("W.js");
To communicate with web worker, you need to implement a onmessage function in the w.js of the worker:
OnMessage =function (evt) {
var data = Evt.data;
PostMessage (data); Send message to main thread
}
Again in the main thread:
Worker.postmessage ("Hello World"); Send message to worker thread
W.onmessage = function (event) {
// ...
}
To turn a nested call into a chained call
This is a bit far from today's topic, but because settimeout is more used, the problem is almost inevitable, so here's a mention. The problem is that the nesting level is too deep, which is especially noticeable when designing JavaScript frameworks:
settimeout (function () {
Logic
settimeout (function () {
Logic
settimeout (function () {
Logic
}, 200);
}, 20);
}, 100);
There is a common optimization approach to optimizing nested calls into chained calls:
Runner.push (function () {
Logic
}, 100)
. push (function () {
Logic
}, 20)
. push (function () {
Logic
}, 200)
. Run ();