Effective JavaScript Item 62 uses nested or named callback functions in asynchronous calls

Source: Internet
Author: User

At the outset, it is somewhat difficult to understand the order of the asynchronous program's invocation. For example, in the following program, starting will be printed first, then finished:

downloadasync (  " file.txt"  , function  (file ) { Console.log  (  " Finished );}); Console.log  (  " Starting ); 

downloadasync method returns immediately after execution, and it simply registers a callback function for downloading this behavior. Because of the JavaScript "Run to finish (run-to-completion)" feature, the currently executing code is not interrupted, so the starting is printed first. The finished will not be output until after the download is complete and JavaScript is taken from the event queue to download the corresponding callback function.

An easy way to think about the order of calls is to think of the asynchronous API as initialization (Initializing) rather than performing (performing) some behavior. In this way of thinking, the above code is easy to understand, the downloadAsync method is simply to initialize the download of this behavior, actually did not make the actual download action.

So for some behavior that depends on the order of execution, such as before the download occurs, we first need to query the download destination URL. It is not possible to do this in the following way:

Db.lookupasync ( "url" ,function(URL) {// ?});d Ownloadasync (URL,function(text) { // Error:url is not boundConsole. Log( "contents of "  +Url+ ": " +text);});

When invoking a downloadAsync method, the URL is actually pointing to undefined. This is also easy to understand, the lookupAsync method only initializes the query behavior, the actual action has not occurred, so the URL as the result of the query is not available.

The most straightforward solution is to use nesting (Nesting), with the characteristics of closures (for closures, see item 11):

Db.lookupasync ( "url" ,function(URL) {Downloadasync (URL,function(text) {Console. Log( "contents of "  +Url+ ": " +Text); });});

Now we put the download behavior in the query behavior registration callback function, through the nature of the closure, in the download method can be accessed to the result URL of the query method.

Using this nesting method to specify the order of asynchronous calls is simple, but as the number of calls increases, the code becomes difficult to read, as follows:

Db.lookupasync ( "url" ,function(URL) {Downloadasync (URL,function(file) {Downloadasync ( "a.txt" ,function(a) {Downloadasync ( "b.txt" ,function(b) {Downloadasync ( "c.txt" ,function(C) {// ...});        });    }); });});

One way to prevent excessive nesting is to declare a nested callback function as a named function, and then pass in the required data as a parameter:

Db.lookupasync ( "url" , DownloadURL);function DownloadURL(URL) {Downloadasync (URL,function(text) { // still nestedShowcontents (URL, text); });}function showcontents(URL,text) {Console. Log( "contents of "  +Url+ ": " +text);}

In order for downloadAsync the callback function of the method to take advantage of the URL, there is a nesting phenomenon in the above code. This nesting can be further eliminated with the Bind method (for the Bind method, refer to item 25):

Db.lookupasync ( "url" , DownloadURL);function DownloadURL(URL) {Downloadasync (URL, showcontents.bind (NULL, URL));}function showcontents(URL,text) {Console. Log( "contents of "  +wr.+ ": " +text);}

Of course, using the Bind method does eliminate too many nesting, but the problem is that you need to declare some named functions. When the number of these functions is too large, there will be no small disturbance. Therefore, there is a common need to strike a balance between using nesting and using the Bind method, and you can use the method of naming functions for important steps, while others use nesting:

Db.lookupasync ( "url" ,function(URL{downloadurlandfiles (URL);});function Downloadurlandfiles(URL) {Downloadasync (URL, downloadfiles.bind (NULL, URL));}function Downloadfiles(URL,file) {Downloadasync ( "a.txt" ,function(a) {Downloadasync ( "b.txt" ,function(b) {Downloadasync ( "c.txt" ,function(C) {// ...});    }); });}

For downloadFiles methods, you can use a more abstract approach (the implementation of this method is described in item 66). Save the downloaded file to an array:

function Downloadfiles(URL,file) {Downloadallasync ([ "a.txt" , "b.txt" , "c.txt" ],function( All) {varA=all[0], b=all[1], C=all[2];// ...});}

downloadAllAsyncMethod can load multiple files in parallel. The proper use of nesting also guarantees the execution sequence of the program. In item 68, you'll learn how to encapsulate the execution flow of a program to make process control easier.

Summarize
    1. Use nested or named callback functions to control the order in which asynchronous behaviors are executed.
    2. Seek a balance in both ways of nesting and naming callback functions.
    3. Tasks that can be processed in parallel, do not serialize them.

Effective JavaScript Item 62 uses nested or named callback functions in asynchronous calls

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.