JavaScript Multi-Threading implementation Method _javascript skills

Source: Internet
Author: User
Tags script tag
Note: The following content is based on the OnLoad event of GIF in IE, so all test ie only
Several pictures that need to be used

Let's look at a simple fact:

Copy Code code as follows:

<script language= "JavaScript" >
var img=new Image ();
Img.src= "Attachment/1178365293_0.gif";
Img.onload=function ()
{
Alert ("If you want to close, press and hold ESC key, and click the Close button");
}
</SCRIPT>


Your IE should pop up a whole bunch of alert windows if you're not too predictable. Attention is "a lot"!

The reason is simple: ie to the multi-frame GIF of the OnLoad event repeated execution, that is, every time the animation is finished, the OnLoad event is executed again.

(Note: Press ESC button will stop the GIF animation playback, it will also stop the OnLoad event execution)

Using this feature we can simulate multithreading implementations:
Look at the following code:

Copy Code code as follows:

Image A onload execution times: <span id= "Threada" >0</span><br>
Image B onload execution times: <span id= "THREADB" >0</span><br>
Image C onload execution times: <span id= "THREADC" >0</span>
<script>
function Img (THREADID,SRC)
{
var img = new Image;
Img.onload = function ()
{
var c = parseint (document.getElementById (ThreadID). InnerHTML);
document.getElementById (ThreadID). Innerhtml=isnan (c)? 1:++c;
}
IMG.SRC = src;
return img;
}

var imga = new IMG ("Threada", "attachment/1178365293_0.gif");
var imgb = new IMG ("Threadb", "attachment/1178365293_1.gif");
var IMGC = new IMG ("THREADC", "attachment/1178365293_2.gif");
</script>


Does that mean something?
Then look at the following code:

Copy Code code as follows:

<script>
by Rimifon
var Threads = new Array;
onload = function ()
{
for (Var c=1; c<501; C + +)
{
Threads.push (New Thread (C));
}
}
function Go (sender)
{
var Isstart = sender.value== "Start All";
for (var x in Threads)
{
THREADS[X]. Start = Isstart;
}
Sender.value = "All" + (Isstart?) Pause ":" "start");
}
function Thread (ID)
{
This. Start = 0;
var cursor = this;
var span = document.createelement ("span");
var counter = document.createTextNode ("0");
Span.appendchild (counter);
var div = document.createelement ("div");
Div.appendchild (document.createTextNode ("thread" + ID + ":"));
Div.style.cursor = "pointer";
Div.onclick = function ()
{
Cursor. Start =!cursor. Start;
}
Div.oncontextmenu = function ()
{
Img.onload = null;
This.removenode (TRUE);
return false;
}
Div.appendchild (span);
Document.body.appendChild (DIV);
var img = new Image;
Img.onload = function ()
{
if (cursor. Start) Counter.data = parseint (counter.data) + 1;
Div.style.backgroundColor = cursor. Start? " #abcdef ":" Yellow ";
}
IMG.SRC = "Images/51js.gif";
}
</script>
<input Type=button value= "Start All" onclick= "Go" >
<input Type=button value= Pop-up dialog box onclick= Alert (' Dialog Test ') >

Part of the code is quoted from Rimifon. (reprinted http://Dnew.cn)
Introduction to JavaScript multithreaded programming
While more and more Web sites are being developed using AJAX technology, building a complex AJAX application is still a challenge. What is the main cause of these difficulties? is an asynchronous communication problem with the server? Or GUI programming problems? Usually these two jobs are done by a desktop program, so why is it so hard to develop an AJAX application that implements the same functionality?

Challenges in AJAX development
Let's use a simple example to understand the problem. Suppose you want to build a tree structure bulletin board System (BBS), it can be based on user requests and server interaction, dynamic loading of each article information, rather than a one-time load from the server all article information. Each article has four related attributes: The ID, the name of the sender, the content of the article, and the array information that contains all of its child article IDs that can be uniquely identified in the system. First, assume that a function named Getarticle () can load an article message. The parameter that the function receives is the ID of the article to be loaded, through which the article information can be obtained from the server. The object it returns contains four attributes related to the article: Id,name,content and children. The routines are as follows:


Copy Code code as follows:

function (ID) {
var a = getarticle (ID);
Document.writeln (A.name + "" + a.content);
}

You may notice, however, that repeatedly calling this function with the same article ID requires repetitive and unhelpful communication with the server. To solve this problem, consider using the function Getarticlewithcache (), which is equivalent to a getarticle () with caching capabilities. In this example, the data returned by Getarticle () is only saved as a global variable:
Copy Code code as follows:

var cache = {};
function Getarticlewithcache (ID) {
if (!cache[id]) {
Cache[id] = getarticle (ID);
}
return Cache[id];
}

Now that the read article has been cached, let's consider the function backgroundload (), which applies the caching mechanism we mentioned above to load all the article information. The purpose is to preload all of its articles from the background when the reader reads an article. Because the article data is tree-like structure, it is easy to write a recursive algorithm to traverse the tree and load all the articles:
Copy Code code as follows:

function Backgroundload (IDS) {
for (Var i=0 i < ids.length; i++) {
var a = Getarticlewithcache (Ids[i]);
Backgroundload (A.children);
}
}

The Backgroundload () function receives an array of IDs as arguments, and then invokes the previously defined Getarticldwithcache () method with each ID, which caches the article that corresponds to each ID. The Backgroundload () method is then recursively called by the child article ID array of the loaded article, so the entire story tree is cached.

So far, everything seems to be perfect. However, as long as you have the experience of developing AJAX applications, you should know that this naïve implementation will not succeed at all, this example is based on the default getarticle () with synchronous communication. However, as a basic principle, JavaScript requires asynchronous communication when interacting with the server because it is single-threaded. In terms of simplicity, it is a good program model to put everything, including GUI events and rendering, into one thread, because there is no need to consider the complexities of thread synchronization. On the other hand, he exposes a serious problem in application development, where a single-threaded environment appears to respond quickly to user requests, but when threads are busy with other things (such as calling Getarticle ()), they cannot respond to the user's mouse clicks and keyboard actions.

What happens if you synchronize communication in this single-threaded environment? Synchronous communication interrupts the execution of the browser until the communication results are obtained. In the process of waiting for the result of the communication, the thread stops responding to the user and remains locked until the call returns because the server's call has not been completed. For this reason, the browser does not respond to user behavior when it waits for a response from the server, so it looks like it is frozen. When executing Getarticlewithcache () and Backgroundload () have the same problem, because they are all based on the getarticle () function. Since downloading all the articles can take a considerable amount of time, for the Backgroundload () function, the browser's freezing over time is a serious problem-now that the browser is frozen, it is not possible to perform background preload data when the user is reading the article. If you do this, you won't be able to read the current article.

As mentioned above, since synchronous communication can cause such a serious problem in use, JavaScript uses asynchronous communication as a basic principle. Therefore, we can rewrite the above program based on asynchronous communication. JavaScript requires an event-driven programming approach to write asynchronous communication programs. On many occasions, you must specify a callback program that will be invoked once the communication response is received. For example, the Getarticlewithcache () defined above can be written like this:
Copy Code code as follows:

var cache = {};
function Getarticlewithcache (ID, callback) {
if (!cache[id]) {
Callback (Cache[id]);
} else {
Getarticle (ID, function (a) {
Cache[id] = A;
Callback (a);
});
}
}

The program also calls the Getarticle () function internally. It should be noted, however, that this version of the Getarticle () function designed for asynchronous communication receives a function as the second argument. When this getarticle () function is invoked, a request is sent to the server as before, but the function now returns quickly rather than waiting for the server to respond. This means that when execution is handed back to the calling program, the server is not responding. In this way, the thread can perform other tasks until it obtains a response from the server and invokes the callback function at this point. Once the server responds, the second parameter of Getarticle () is invoked as a predefined callback function, and the server's return value is its parameter. Similarly, Getarticlewithcache () also needs to make changes to define a callback parameter as its second argument. This callback function is called in the callback function passed to Getarticle (), so it can be executed at the end of the server communication.

You may have thought it was quite complicated to make these changes, but the changes to the Backgroundload () function would be more complicated, and it would be rewritten as a way to handle callback functions:
Copy Code code as follows:

function Backgroundload (IDs, callback) {
var i = 0;
function L () {
if (I < ids.length) {
Getarticlewithcache (ids[i++], function (a) {
Backgroundload (A.children, L);
});
} else {
Callback ();
}
}
L ();
}

The modified backgroundload () function seems to be a far cry from our previous function, but the functionality they implement is not the same. This means that both functions accept an ID array as an argument, a Getarticlewithcache () is invoked for each element in the array, and then a recursive call to Backgroundload () has been obtained for the child article ID. But the same is the circular access to the array, the new function is not very good to identify, in the previous program is a For loop statement completed. Why are the two sets of functions that implement the same function so vastly different?

The difference stems from the fact that any function must return immediately, such as Getarticlewithcache (), when it encounters a need to communicate with the server. Unless the original function is not in execution, the callback function that should accept the server response cannot be invoked. For JavaScript, it is not possible to interrupt a program during a loop and start executing the program later from this breakpoint, such as a for statement. Therefore, this example uses recursive transfer callback function to implement loop structure rather than a traditional circular statement. For those familiar with the continuous delivery style (CPS), this is a manual implementation of a CPS, because the loop syntax is not available, so even simple procedures like the one mentioned above are complicated to write. The problems associated with event-driven programming are control flow problems: loops and other control-flow expressions can be difficult to understand.

Here's another question: if you convert a function that does not use asynchronous communication into a function that uses asynchronous communication, the overridden function will require a callback function as a new parameter, which poses a big problem for existing APIs because internal changes do not limit the impact internally, It is the APIs that cause overall chaos and the changes to other users of the API.

What is the root cause of these problems? Yes, it is the JavaScript single-threaded mechanism that causes these problems. The execution of asynchronous communication in a single thread requires event-driven programming and complex statements. If the program is waiting for a response from the server, and there is another thread that can handle the user request, then this complex technology will not be needed.

Try multithreaded Programming
Let me introduce concurrent.thread, a library that allows JavaScript to be multithreaded, and it can be used to greatly mitigate the difficulties associated with asynchronous communication in AJAX development mentioned above. This is a free software library, written in JavaScript, with the premise of complying with the two Protocols of Mozilla Public License and GNU General Public License. You can download the source code from their website.

Download and use the source code right away! Suppose you have saved the downloaded source code in a folder named Concurrent.Thread.js, and before doing anything, run the following program, which is a very simple feature implementation:
Copy Code code as follows:

<script type= "Text/javascript" src= "Concurrent.Thread.js" ></script>
<script type= "Text/javascript" >
Concurrent.Thread.create (function () {
var i = 0;
while (1) {
Document.body.innerHTML + + i++ + "<br>";
}
});
</script>

Executing this program will display the numbers starting with 0, one after the other, and you can scroll to see it. Now let's take a closer look at the code, which uses the while (1) condition to create a loop that does not stop, and normally a JavaScript program like this that keeps using one and only one thread will cause the browser to look like it's frozen, and will naturally not allow you to roll the screen. So why does the above program allow you to do this? The key point is the Concurrent.Thread.create () statement above while (1), which is a method provided by this library that creates a new thread. The function passed in as a parameter is executed in this new thread, let's fine-tune the program as follows:
Copy Code code as follows:

<script type= "Text/javascript" src= "Concurrent.Thread.js" ></script>
<script type= "Text/javascript" >
function f (i) {
while (1) {
Document.body.innerHTML + + i++ + "<br>";
}
}
Concurrent.Thread.create (f, 0);
Concurrent.Thread.create (f, 100000);
</script>

There's a new function in this program F () that can repeat the numbers, it is defined at the beginning of the program segment, and then the two create () method is called with the F () parameter, and the second parameter passed to the Create () method is passed to F () without modification. To execute this program, you will first see some decimal numbers starting with 0, followed by some large numbers starting with 100,000, followed by the number in the previous decimal order. You can observe that the program displays the decimal and large numbers alternately, indicating that two threads are running at the same time.

Let me show you another usage of concurrent.thread. The example above calls the Create () method to make a new thread. It is also possible to do so without invoking any APIs in the library. For example, the preceding example can be written like this:
Copy Code code as follows:

<script type= "Text/javascript" src= "Concurrent.Thread.js" ></script>
<script type= "Text/x-script.multithreaded-js" >
var i = 1;
while (1) {
Document.body.innerHTML + + i++ + "<br>";
}
</script>

Within the script tag, it's easy to write an infinite loop with JavaScript. You should notice the type attribute within the tag, which is a very strange value (text/x-script.multithreaded-js), if the attribute is placed inside the script tag, Then Concurrent.thread will execute the program between tags in a new thread. You should remember that, as in this example, the Concurrent.thread library must be included.

With Concurrent.thread, it is possible to switch the execution environment between threads freely, even if your program is long and continuous. We can briefly discuss how to perform this operation. In short, code conversion is required. Roughly speaking, the function passed to create () is first converted to a string, then rewritten until it can be executed in batches. These programs can then be implemented progressively according to the scheduler. The scheduler is responsible for coordinating multiple threads, in other words, it can be adjusted at the appropriate time so that each modified function will get the same chance to run. Concurrent.thread actually does not create a new thread, it simply simulates a multithreaded environment based on the original single-threaded path.

Although the converted function appears to run in a different thread, there is actually only one thread doing all of this. Performing synchronous communication within a converted function can still cause the browser to freeze, and you may think that the previous problems were not resolved at all. But you don't have to worry, Concurrent.thread provides a custom communication library that uses JavaScript to implement asynchronous communication, designed to allow other threads to run when a thread waits for a response from the server. This communication stock is under Concurrent.Thread.Http. Its usage is as follows:
Copy Code code as follows:

<script type= "Text/javascript" src= "Concurrent.Thread.js" ></script>
<script type= "Text/x-script.multithreaded-js" >
var req = Concurrent.Thread.Http.get (URL, ["Accept", "*"]);
if (Req.status = = 200) {
alert (Req.responsetext);
} else {
alert (Req.statustext);
}
</script>

The Get () method, as its name implies, can obtain the contents of the specified URL by using the HTTP getting method, which takes the target URL as the first parameter and an array representing the HTTP request header as the optional second argument. The Get () method interacts with the server and returns a XMLHttpRequest object as the return value when a response is received from the server. When the Get () method returns, the server response has been received, so there is no need to use the callback function to receive the result. Naturally, there is no need to worry about the browser freezing when the program waits for a response from the server. In addition, there is a post () method that can be used to send data to the server:
Copy Code code as follows:

<script type= "Text/javascript" src= "Concurrent.Thread.js" ></script>
<script type= "Text/x-script.multithreaded-js" >
var req = Concurrent.Thread.Http.post (URL, "Key1=val1&key2=val2");
alert (Req.statustext);
</script>

The post () method takes the destination URL as the first argument, and the content to be sent as the second argument. As with the Get () method, you can also use the request header as an optional third parameter.

If you use this library to implement the Getarticle () method in the first example, you will soon be able to write Getarticlewithcache (), Backgroundload () in the simple way that the article starts with the example. and other functions that have called the Getarticle () method. Even if the version of Backgroundload () is reading the article data, as usual there is another thread can respond to user requests, so the browser will not freeze. Now, can you understand how practical it is to use multithreading in JavaScript?

Want to know more
I've introduced you to a library where you can apply multithreading in javascript: Concurrent.thread. The content of this article is only a very elementary thing, if you want to understand more deeply, I recommend you to see the tutorial. It provides more on Concurrent.thread usage and lists documents available for advanced users, which are the most suitable materials for getting started. It's also nice to visit their website, which provides more information.

About the author
Daisuke Maki: After graduating from the Natural Science division of the Liberal Arts Institute of International Christian (obtaining a Bachelor of Arts degree), he is also pursuing a master's degree in information studies at the Graduate School of Electro-communications University. Ajax that specializes in web development and application JavaScript. He developed the Concurrent.thread. This design was applied in the 2006 fiscal year in Explatory Software project, which was guided by the Japan Information Technology Promotion Agency (IPA).

He currently has a master's degree in engineering and is enrolled in a Ph. D. in graduate school at Electro-communications University.
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.