JavaScript Asynchronous Programming

Source: Internet
Author: User
Tags emit event listener readfile install node

This article transferred from: http://www.cnblogs.com/nullcc/p/5841182.html

JavaScript is single-threaded at least at the language level, so asynchronous programming is especially important.

Take Nodejs, the shell is a layer of JS language, this is the user's level of operation, at this level it is single-threaded operation, that is, we can not like Java, Python such language at the language level using multithreading capabilities. Instead, asynchronous programming techniques have been used extensively in NODEJS programming for efficient use of hardware, as well as for non-synchronous blocking. But Nodejs in the bottom of the implementation is actually using multithreading technology, but this layer of users is transparent to users, Nodejs help us do almost all the management work, we do not have to worry about locks or other multi-threaded programming will encounter problems, just write our asynchronous code is good.

Two. JavaScript Asynchronous Programming method

ES 6 Before:

* Callback function
* Event Monitoring (event publish/subscribe)
* Promise Object

ES 6:

* Generator function (co-coroutine)

ES 7:

* Async and await

PS: If you want to run the following example, install node v0.11 above, at the command line using the form of node [filename. js] To run, some of the code needs to open special options, will be described in specific examples.

1. Callback function

Callback functions are very common in JavaScript, and it is generally necessary to use a callback function when performing an operation after a time-consuming operation.

Example 1:

  1  //  One timer   2  function   timer (time, callback) {  3  setTimeout (function   () {  4   callback ();   5  }, time);   6  }   7   8  timer (function   {  9  console.log (12310 }) 

Example 2:

// output file contents after reading a file var fs = require (' FS '); Fs.readfile (thefunction(err, data)    {if  ( ERR) {        throw  err;    }    Console.log (data);});

Example 3:

1 //nested callbacks, read a file after the output, and then read another file, note that the file is ordered to be output, first text1.txt after Text2.txt2 varFS = require (' FS ');3 4Fs.readfile ('./text1.txt ', ' UTF8 ',function(err, data) {5Console.log ("Text1 file content:" +data);6Fs.readfile ('./text2.txt ', ' UTF8 ',function(err, data) {7Console.log ("Text2 file content:" +data);8     });9});

Example 4:

// callback Hell doSomethingAsync1 (function() {    doSomethingAsync2()        { DOSOMETHINGASYNC3 (function() {            doSomethingAsync4() {                DoSomethingAsync5 (function() {                    //  code ...                 });            });        });    });});

By observing the above 4 examples, you can find a problem, in the case of the number of nested layers of callback function is not deep, the code is easy to understand and maintain, once the nesting layer deepens, there will be "callback pyramid" problem, like example 4, if each of the callback function in this contains a lot of business logic , the entire code block becomes very complex. From the point of view of logic correctness, there are no problems with the writing of these callback functions, but as the business logic grows and becomes more complex, the shortcomings of this writing are immediately revealed and it is too painful to maintain them, which is called "Callback Hell (Callback Hell)".
One way to measure the complexity of the callback hierarchy is, in Example 4, to assume how much refactoring pain we need to endure before the DOSOMETHINGASYNC2 takes place in DoSomethingAsync1.

Another problem with the callback function is that we cannot catch the exception in the callback function outside of the callback function, which we used to do when dealing with exceptions:

Example 5:

1 Try {2     // Do something may cause exception. 3 }4catch(e) {5     //Handle Exception ...  6 }

In the synchronization code, this is fine. Now consider the execution of the following code:

Example 6:

1 varFS = require (' FS ');2 3 Try{4Fs.readfile (' not_exist_file ', ' UTF8 ',function(err, data) {5 console.log (data);6     });7 }8 Catch(e) {9Console.log ("Error Caught:" +e);Ten}

What do you think will be exported? The answer is undefined. We tried to read a nonexistent file, which would of course throw an exception, but the outermost try/catch statement could not catch the exception. This is caused by the execution mechanism of asynchronous code.

Tips: Why is an exception in an async code callback function not captured by the outermost try/catch statement?

Asynchronous calls are generally divided into two stages, which commit the request and process the result, which are called by the event loop between the two phases, which belong to two different event loops (ticks) and are not associated with each other.

An asynchronous invocation typically specifies the action to be performed after the asynchronous operation completes by passing in the callback. Instead, the asynchronous call ontology and callback belong to different event loops.

The Try/catch statement can only catch the exception of the second event loop, and callback is powerless.

That is, once we throw an asynchronous I/O request in an asynchronous calling function, the asynchronous call function returns immediately, and this asynchronous call function has nothing to do with this asynchronous I/O request.

2. Event monitoring (event publish/subscribe)

Event snooping is a very common asynchronous programming pattern, which is a typical logical separation method and is useful for decoupling code. In general, we need to consider which parts are invariant, which are easily changeable, and encapsulate the invariant parts inside the component for external invocation, and the custom part is exposed to the outer processing. In a sense, the design of an event is the interface design of the component.

Example 7:

  1  //  Publish and Subscribe events   2   3  var  events = require (' Events '   4  var  emitter = new   events. Eventemitter ();   5   6  emitter.on (' event1 ', function    7   Console.log (message);   8  });   9  10  emitter.emit (' event1 ', "message for You "); 

This asynchronous programming approach using Event listener processing is well suited for scenarios that require a high degree of decoupling. For example, in a previous game server project, when the character attribute changes, it needs to be written to the persistence layer. The solution is to write a subscriber, subscribe to the ' Save ' event, let the Publisher object (here is the character object) to send an event name directly with emit and carry the corresponding parameter when the data needs to be saved, the Subscriber receives this event information and handles it.

3.Promise objects

ES 6 Zhongyuan provides the Promise object, the Promise object represents an event (typically an asynchronous operation) in which a future will know the result, and this event provides a unified API for further processing.
Using the Promise object can express the asynchronous operation by the process of the synchronous operation, avoids the layer nested asynchronous callback, the code is more clear and easy to maintain.

Promise.prototype.then ()

The Promise.prototype.then () method returns a new Promise object, so you can use chained notation, that is, one then and then the other. If the previous callback function returns a Promise object, the latter callback function waits for the first promise object to have a result before it is called further.

Example 8:

1 //ES 6 Native Promise Example2 varFS = require (' FS ')3 4 varRead =function(filename) {5     varPromise =NewPromise (function(Resolve, reject) {6Fs.readfile (filename, ' UTF8 ',function(err, data) {7             if(err) {8 reject (err);9             }Ten resolve (data); One         }) A     }); -     returnpromise; - } the  -Read ('./text1.txt ')) -. Then (function(data) { - console.log (data); +},function(err) { -Console.log ("ERR:" +err); +});

In the above code, the Read function is promise, and in the Read function, an Promise object is instantiated, and the constructor of promise takes a function as a parameter, and the two parameters of the function are resolve method and reject method respectively. If the asynchronous operation succeeds, the Resolve method is used to change the state of the Promise object from "unfinished" to "done" (that is, from pending to resolved), and if an asynchronous operation fails, The Reject method is used to change the state of the Promise object from "unfinished" to " Failed "(that is, from pending to rejected), the read function returned the Promise object. After the promise instance is generated, you can use the then method to specify the callback function for the Resolve method and the Reject method, respectively.

In this example, the promise constructor parameter is a function in which we write the code of the asynchronous operation, in the callback of the asynchronous operation, we choose whether to execute the Resolve method or the Reject method according to the ERR variable. In general, the argument that calls the Resolve method is the data that the asynchronous operation obtains (if any), but it may also be another promise object that indicates that the result of an asynchronous operation might be a value or another asynchronous operation, and that the argument to the calling reject method is the Err parameter of the asynchronous callback call.

When you call the Read function, you actually return an promise object that specifies the successful and failed operation of the asynchronous operation by invoking the then method on the Promise object and passing in the Resolve method and reject method.

Example 9:

1 //native Primose Sequential nested callback example2 varFS = require (' FS ')3 4 varRead =function(filename) {5     varPromise =NewPromise (function(Resolve, reject) {6Fs.readfile (filename, ' UTF8 ',function(err, data) {7             if(err) {8 reject (err);9             }Ten resolve (data); One         }) A     }); -     returnpromise; - } the  -Read ('./text1.txt ')) -. Then (function(data) { - console.log (data); + returnRead ('./text2.txt ')); - }) +. Then (function(data) { A console.log (data); at});

In the sequential nested callback of the promise, the first then method returns the contents of the Text1.txt after the read ('./text2.txt '), noting that this is the key, where a new promise instance is actually returned, The second then method specifies the callback function that reads the Text2.txt file asynchronously. This promise sequential nested callback, which resembles synchronous invocation, is characterized by a large number of then methods, with slightly more code redundancy.

Exception handling

Promise.prototype.catch ()

The Promise.prototype.catch method is an alias for Promise.prototype.then (null, rejection) that specifies the callback function when an error occurs.

Example 9:

1 varFS = require (' FS ')2 3 varRead =function(filename) {4     varPromise =NewPromise (function(Resolve, reject) {5Fs.readfile (filename, ' UTF8 ',function(err, data) {6             if(err) {7 reject (err);8             }9 resolve (data);Ten         }) One     }); A     returnpromise; - } -  theRead ('./text1.txt ')) -. Then (function(data) { - console.log (data); -     returnRead (' Not_exist_file '); + }) -. Then (function(data) { + console.log (data); A }) at.Catch(function(err) { -Console.log ("Error Caught:" +err); - }) -. Then (function(data) { -Console.log ("Completed"); -})

。。。。。。

JavaScript Asynchronous Programming

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.