Introduction to the principles and implementation skills of Asynchronous javascript _ javascript tips-js tutorial

Source: Internet
Author: User
Because of work requirements, I need to write a script on the Web page to submit data to the system in batches through the web page. So I thought of the Greasemonkey plug-in, so I started to write and found that the problem was solved smoothly because of the work needs, I had to write a script on the webpage, batch submit data to the system through the web page. So I thought of the Greasemonkey plug-in, so I started to write and found that the problem was solved smoothly. However, when summing up and sorting out scripts, I habitually asked myself the following question: can it be simpler?
Of course, my answer is "yes ".

First, review my data batch submission requirements: I have a batch of user data to be inserted into the system, but because the system database table structure is not the deciding factor, it cannot be converted to SQL statement insertion. There are nearly 200 pieces of data to be inserted, that is, it takes one day to manually enter the data into the system. As a programmer, of course, I will not do such silly things. I must solve it with a program. This programming process took me one day. Compared with manual input, my additional income is this blog, which is definitely cost-effective!

The programming platform does not take time to choose to directly write its own script based on Greasemonkey. the browser is firefox of course. Script process:
Pre-store the data to be inserted in the script
Simulate Mouse clicking to open the input window on the page
Enter the data in the input window, and click Submit to submit the data to the system.
It repeats until all data is processed.

The technical difficulties here are:
Open the input window and wait for an irregular period of time, depending on the network conditions.
Submit the data to the backend. You must wait for the processing to complete before you can cycle the next data.
If I am a cainiao, I certainly write an application logic similar to this:

The Code is as follows:


For (var I = 0; I <dataArray. length; ++ I)
{3: clickButtonForInputWindow ();
WaitInputWindow ();
EnterInputData (dataArray [I]);
ClickSubmitButton ();
WaitInputWindowClose ();
}


In fact, all browsers will be written into a white screen, and will be forcibly terminated after several minutes, prompting "no response. The reason is that when the browser calls javascript, the main interface stops responding because the cpu is handed over to js for execution and there is no time to process interface messages.

To meet the "don't lock" requirement, we can modify the script to this:

The Code is 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 can we use these two functions more elegantly for asynchronous operations? At present, the simple answer is Lao Zhao's Wind. js. Although I have never used this function library, calling $ await alone is consistent with my concise requirements. However, for a single file script like me, downloading an external js library online is obviously not as fast and cool as copying a piece of code that supports asynchronous operations.

So I decided to find another way, to do an asynchronous function library that is not compiled and easy to use, and can be more capable of copying & Paste.

Before Asynchronization, let's recall several structure types of synchronization operations:

Order: The statement is executed sequentially.
Judgment: A judgment statement.
Loop: strictly speaking, it should be a jump (goto), but most modern languages cancel goto. The loop should actually be a composite structure, which is the combination of if and goto.
There are two difficulties in asynchronous operations:

Asynchronous judgment: In asynchronous cases, the judgment is basically that the detection conditions are met, and then some actions are executed.
Asynchronous order: after each operation in the sequence, the control is handed back, waiting for the next step to continue. The difficulty is how to maintain order. Especially when two sequential actions are mixed with an Asynchronous Loop.
Asynchronous Loop: after each loop, the control is handed back to the browser, so that the loop ends until the running ends.
The simplest implementation is of course Asynchronous Loop. My implementation code is as follows:

The Code is 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 content is: if the fn function return value is not false, the next setTimeout registration call will continue.

In fact, the logic of "waiting and executing" is basically an Asynchronous Loop. The implementation method is as follows:

The Code is as follows:


AsyncWhile (function (){
If (xxxCondition = false)
Return true; // indicates that the loop continues.
Else
DoSomeThing ();
Return false; // indicates that the loop does not need to be continued.
});


For the logic that is not waiting and executed, a simple setTimeout is enough.
Asynchronization is easy. It is difficult to implement the order in Asynchronization. The earliest reason was that I had to implement three steps, but the second part was an asynchronous 100 multiple cycles. That is to say, the three steps I want to implement are actually 103 sequential asynchronous operations. In order to find out how to implement a responsive wait in the browser, I broke my head, found only the implementation in one firefox, and applied for privileged calls.
Finally, I came up with a simple method that introduced the "Execution Chain" concept. All the registration functions of the same Execution Chain are sequential, there is no relationship between different execution chains. In addition, mutex and other concepts are not provided. If you want to synchronize them, check them in the code.
In the same execution chain, an execution token is saved. Execution is allowed only when the token matches the function serial number. This ensures the order of asynchronous execution.

The Code is 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); // delayed startup for debugging reasons
}


Therefore, an asynchronous js function library that supports Copy & Paste is complete. An example is as follows:

The Code is 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, I 'd like to say sorry to everyone. Many friends who just want to get code may be disappointed. If you really don't know how to deal with these redundant line numbers, you can learn about regular expression replacement. We recommend using 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.