Introduction to the principles and implementation techniques of asynchronous JavaScript _javascript skills

Source: Internet
Author: User
Tags goto wrapper
Because of the needs of the work, I want to write a script at the end of the Web page, the data submitted to the system in batches. So I thought of the Greasemonkey plug-in, so began to write, found that the problem solved very smoothly. But in summarizing and collating the script, I habitually asked myself a question: can you be more simple?
My answer, of course, is "can".

First, review my data batch submission requirements: I have a batch of user data to insert into the system, but because the system library table structure is not a determinant, it cannot be converted to SQL statement inserts. There are nearly 200 data to be inserted, that is, silly to the system manually, estimated to be 1 days. As a programmer, of course, do not do such a silly thing, I must use the program to solve. The programming process took me 1 days to spend. Compared to manual entry, my extra income is this blog post, absolutely cost-effective!

The programming platform chooses not to spend the time, directly chooses based on Greasemonkey writes own script, the browser certainly is the Firefox. How the script works:
Pre-storing data to insert in a script
Simulate mouse clicks, open the Input window in the page
Enter the data into the input window and simulate clicking the "Submit" button to submit the data to the system.
Loop until all the data is processed.

the technical difficulty here is:
Open the input window, you need to wait for an unscheduled time, depending on the network situation.
Submit data to the background, you need to wait for processing before you can cycle the next data.
If I were a rookie, I would certainly write an application logic like this:
Copy Code code as follows:

for (var i = 0; i < dataarray.length; ++i)
{3:clickbuttonforinputwindow ();
Waitinputwindow ();
Enterinputdata (Dataarray[i]);
Clicksubmitbutton ();
Waitinputwindowclose ();
}

In fact, all browsers would fall into a screen and be forced to terminate after a few minutes prompting "no response". The reason is that the browser when invoking JavaScript, the main interface is to stop responding, because the CPU to the implementation of JS, there is no time to deal with interface messages.

In order to satisfy the "no deadlock" requirement, we can modify the script to this:
Copy Code code as follows:

for (var i = 0; i < dataarray.length; ++i)
{
SetTimeout (Clickbuttonforinputwindow);
...
SetTimeout (Waitinputwindowclose);
}

In fact, settimeout and SetInterval are the only operations that the browser can support asynchronously. How do you use these two functions more gracefully to implement asynchronous operations? At present, the simple answer is Lao Zhao's wind.js. Although I have not used this library, but only $await calls, is consistent with my consistent demand for simplicity. But for the script of a single file like mine, to download an external JS library on the Internet, it's obviously better to have a copy of the code that supports the asynchronous operation coming up fast and cool.

So I decided to do something else and do a library of asynchronous functions that do not compile and can be copy&paste more easily.

Before we say Asynchrony, let's recall some of the structural types of synchronous operations:

Order: is the sequential execution of the statement
Judgment: is the Judgment statement
Loop: It's strictly a jump (goto), but most modern languages cancel Goto. The loop should actually be a composite structure, a combination of if and Goto.
The difficulties of asynchronous operations are in two places:

Asynchronous judgment: The judgments in asynchronous situations are basically satisfied with the detection conditions, and then perform certain actions.
Asynchronous order: Control is returned after each step in the order, waiting to continue the next step in the next time slice. The difficulty is how to keep the order. Especially in the middle of the two sequence of movements with an asynchronous loop.
Asynchronous loops: Control is returned to the browser after each loop, so that it loops until the end of the run.
The simplest implementation, of course, is the asynchronous loop, and my implementation code is as follows:
Copy Code code as follows:

Function Asyncwhile (FN, interval)
{
if (fn = null | | (typeof (FN)!= "string" && typeof (FN)!= "function")
Return
var wrapper = function ()
{
if (typeof (fn) = "function"? FN (): eval (FN))!== false)
settimeout (wrapper, interval = null? 1:interval);
}
Wrapper ();
}

The core is this: if the FN return value is not false, the next settimeout registration call continues.

In fact, the "Wait and execute" logic is essentially an asynchronous loop problem. An example of how to implement this scenario is as follows:
Copy Code code as follows:

Asyncwhile (function () {
if (xxxcondition = = False)
return true; Indicates a continuation of the loop
Else
DoSomething ();
return false; means you don't need to keep looping.
});

For the logic that is not waiting and executing, a simple settimeout is OK.
Asynchronous easy, the realization of the order in the asynchronous is called difficulty. The earliest cause was that I wanted to implement 3 steps, but the second one was an asynchronous 100-times loop. That is, I want to implement the 3-step operation, in fact, 103 times the sequential asynchronous operation. For a way to implement a responsive wait in the browser, find a broken head, only to find a Firefox implementation, but also to request a privilege call.
Finally came up with a simple method, that is, the introduction of the "Execution chain (Execution Chain)" concept, the same execution chain of all registration functions are sequential, the different execution chain has no relationship. In addition, you do not provide concepts such as mutexes (mutexes), and if you want to synchronize, check yourself in your code.
In the same execution chain, an execution token is saved, allowing execution only if the token matches the function ordinal, which guarantees the order of the asynchronous execution.
Copy Code code as follows:

function Asyncseq (Funcarray, Chainname, Abortwhenerror)
{
if (typeof (Funcarray) = = "function")
Return Asyncseq ([Funcarray], Chainname, abortwhenerror);

if (Funcarray = null | | funcarray.length = 0)
Return

if (Chainname = = null) Chainname = "__default_seq_chain__";
var Tinfos = Asyncseq.chaininfos = Asyncseq.chaininfos | | {};
var tinfo = Tinfos[chainname] = Tinfos[chainname] | | {count:0, Currentindex:-1, Abort:false};

for (var i = 0; i < funcarray.length; ++i)
{
Asyncwhile (function (item, TINDEX) {
return function () {
if (Tinfo.abort)
return false;
if (Tinfo.currentindex < Tindex)
return true;
else if (Tinfo.currentindex = = Tindex)
{
try{
Item ();
}
catch (e) {
if (abortwhenerror) Tinfo.abort = true;
}
finally{
Tinfo.currentindex + +;
}
}
Else
{
if (abortwhenerror) Tinfo.abort = true;
}
return false;
};
} (Funcarray[i], Tinfo.count + +));
}

settimeout (function () {
if (Tinfo.count > 0 && tinfo.currentindex = = 1)
Tinfo.currentindex = 0;
},20); For debugging reasons, a delayed start is added
}

Thus, a library of asynchronous JS functions that supports copy&paste is completed. Examples of specific uses are as follows:
Copy Code code as follows:

function Testasync ()
{
Asyncseq ([function () {println ("aSyncSeq-0");}
, function () {println ("aSyncSeq-1");}
, function () {println ("aSyncSeq-2");}
, function () {println ("aSyncSeq-3");}
, function () {println ("aSyncSeq-4");}
, function () {println ("aSyncSeq-5");}
, function () {println ("aSyncSeq-6");}
, function () {println ("aSyncSeq-7");}
, function () {println ("aSyncSeq-8");}
, function () {println ("aSyncSeq-9");}
, function () {println ("aSyncSeq-10");}
, function () {println ("aSyncSeq-11");}
, function () {println ("aSyncSeq-12");}
, function () {println ("aSyncSeq-13");}
, function () {println ("aSyncSeq-14");}
, function () {println ("aSyncSeq-15");}
, function () {println ("aSyncSeq-16");}
, function () {println ("aSyncSeq-17");}
, function () {println ("aSyncSeq-18");}
, function () {println ("aSyncSeq-19");}
, function () {println ("aSyncSeq-20");}
, function () {println ("aSyncSeq-21");}
, function () {println ("aSyncSeq-22");}
, function () {println ("aSyncSeq-23");}
, function () {println ("aSyncSeq-24");}
, function () {println ("aSyncSeq-25");}
, function () {println ("aSyncSeq-26");}
, function () {println ("aSyncSeq-27");}
, function () {println ("aSyncSeq-28");}
, function () {println ("aSyncSeq-29");}
]);

Asyncseq ([function () {println ("Asyncseq test-chain-a0");}
, function () {println ("Asyncseq test-chain-a1");}
, function () {println ("Asyncseq test-chain-a2");}
, function () {println ("Asyncseq test-chain-a3");}
, function () {println ("Asyncseq test-chain-a4");}
, function () {println ("Asyncseq test-chain-a5");}
, function () {println ("Asyncseq test-chain-a6");}
, function () {println ("Asyncseq test-chain-a7");}
, function () {println ("Asyncseq test-chain-a8");}
], "Test-chain");

Asyncseq ([function () {println ("asyncseq-a0");}
, function () {println ("asyncseq-a1");}
, function () {println ("asyncseq-a2");}
, function () {println ("Asyncseq-a3");}
, function () {println ("asyncseq-a4");}
, function () {println ("Asyncseq-a5");}
, function () {println ("Asyncseq-a6");}
, function () {println ("Asyncseq-a7");}
, function () {println ("Asyncseq-a8");}
]);
}

var textArea = null;

function println (text)
{
if (TextArea = null)
{
TextArea = document.getElementById ("text");
Textarea.value = "";
}

Textarea.value = textarea.value + text + "\ r \ n";
}

Finally, to everyone to say sorry, a lot of just want to get the code friend is afraid to disappoint, if you really do not know how to deal with these extra line number, you can learn about the replacement of regular expressions, recommend the use of UltraEdit.
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.