JavaScript Learning Guide's callback Problem _ basics

Source: Internet
Author: User
Tags generator

Callback to Hell

For JavaScript programmers, the process callback is homely, but the processing level of the callback is not so good, the following example code fragment with a three-layer callback, and then brain more layers of scenes, is simply sour, this is the legendary callback hell.

GetDirectories (function (dirs) {
  GetFiles (dirs[0), function (files) {
    getcontent (files[0), function (file, Content) {
      console.log (' filename: ', file);
      Console.log (content);
    });
  };
 
function GetDirectories (callback) {
 settimeout (function () {
  callback (['/home/ben ']);
 }, 1000);
 
function GetFiles (dir, callback) {
  settimeout (function () {
    callback (dir + '/test1.txt ', dir + '/ Test2.txt ']);
  }, 1000
}
 
function getcontent (file, callback) {
  settimeout (function () {
    Callback (file, ' content ');
  }, 1000)
}

Solution

There are many asynchronous solutions in the biosphere that can handle the problem of callback hell, such as Bluebird, Q, etc., this article focuses on the support for asynchronous programming in the ECMAScript 6/7 specification.

ES6 Promise

Promise is a solution of asynchronous programming and a sharp weapon to solve the problem of callback hell.

Promise in the JavaScript Biosphere was accepted by the Dojo framework in 2007 to add Dojo. The Deferred function. With Dojo. The popularity of Deferred, in 2009 Kris ZYP proposed the COMMONJS promises/a specification. Subsequently, a large number of Promise were realized in the biosphere, including Q.js, Futuresjs and so on. Of course Promise's popularity is largely due to the existence of jquery, but jquery does not fully comply with the COMMONJS promises/a specification. Then, as you can see, the ES 6 specification contains Promise.
MDN in the Promise is described in this way:

The Promise object is a proxy that returns a value that is not necessarily known when the Promise object is created. It allows you to specify the processing method for the success or failure of an asynchronous operation. This allows the asynchronous method to return a value like a synchronous method: The asynchronous method returns a value that contains the original return
The following code is the example in the "Callback Hell" section that is implemented by Promise, which seems to be not very concise, but is more maintainable and readable than traditional hierarchical callbacks.

GetDirectories (). Then (function (dirs) {return
  GetFiles (dirs[0));
Then (function (files) {return
  getcontent (files[0]);
}). Then (function (val) {
  console.log (' filename: ', val.file);
  Console.log (val.content);
});
 
function GetDirectories () {return
  new Promise (function (resolve, reject) {
    settimeout (function ()
    { Resolve (['/home/ben ']);
   }, 1000)
 
;} function GetFiles (dir) {return
  new Promise (function (resolve, reject) {
    settimeout (function () {
      Resolve ([dir + '/test1.txt ', dir + '/test2.txt ']);
    }, 1000)
 
;} function getcontent (file) {return
  new Promise (function (resolve, reject) {
    settimeout (function ()
      { Resolve ({file:file, Content: ' content '});
    }, 1000);
  }

ES6 Generator

Promise's implementation is not simple enough, we need a better choice, CO is one of the options. Co is an asynchronous flow controller based on generator (generator), and understanding generator is first needed before understanding Co. Students familiar with C # should be aware that the C # 2.0 version introduces the yield keyword for iterative generators. The ES 6 generator is similar to C # and uses the yield syntax sugar, which implements the state machine internally. Specific use can refer to the MDN document function* section, the principle can refer to Alloyteam team Blog in-depth understanding generator. Using CO cleverly combines ES6 generator and ES6 Promise to make asynchronous calls more harmonious.

Co (function* () {
  var dirs = yield getdirectories ();
  var files = yield GetFiles (dirs[0]);
  var contentval = yield getcontent (files[0));
  Console.log (' filename: ', contentval.file);
  Console.log (contentval.content);
});

Co is very ingenious, its core code can simplify the following example, the general idea is to use the recursive traversal generator until the state is complete, of course, CO do more.

Rungenerator ();
 
function* run () {
  var dirs = yield getdirectories ();
  var files = yield GetFiles (dirs[0]);
  var contentval = yield getcontent (files[0));
  Console.log (' filename: ', contentval.file);
  Console.log (contentval.content);
}
 
function Rungenerator () {
  var gen = run ();
 
  function go [result] {
    if (result.done) return;
    Result.value.then (function (r) {Go
      (Gen.next (R));}
    );
 
  Go (Gen.next ());
}

ES7 async/await

ES6 generator is really good, but unfortunately needs the support of Third-party libraries. The good news is that ES 7 will introduce the ASYNC/AWAIT keyword to solve the problem of asynchronous invocation perfectly. Well,. NET is a step ahead, and the. NET Framework 4.5 has been the first to support it.
The next code is written like this:

Run ();
Async function Run () {
  var dirs = await getdirectories ();
  var files = await GetFiles (dirs[0]);
  var contentval = await getcontent (files[0));
  Console.log (' filename: ', contentval.file);
  Console.log (contentval.content);
}

Conclusion

From the classic callback asynchronous programming, to the ES6 Promise specification to the improvement of asynchronous programming, and then to the co-integration ES Generator elegant processing, finally ES7 async/await perfect finale, can let us know why ECMAScript will appear these characteristics and solutions What is the problem, more clearly see the development of JavaScript asynchronous programming context.

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.