All web operations in JavaScript, browser events, must be executed asynchronously. As we all know, asynchronous programming in JavaScript can only be done with first-class citizen functions in the JavaScript language: this approach means that we can take one function as an argument to another function, and inside that function we can call the function passed in (the callback function).

let fs = require('fs');
 fs.readFile('./1.txt'.'utf8'.function(err,data){
 ifConsole. log(err) {// If err has a value, the program failed console.log(err); }else{// If error is empty, success is achieved, there is no error console.log(data); }})Copy the code

The problem with callback functions

    1. Failed to catch an error try catch
    1. Can’t return
    1. The callback hell
function read(filename){
 fs.readFile(filename,'utf8'.function(err,data){
 throw Error('Wrong')
 ifConsole. log(err) {// If err has a value, the program failed console.log(err); }else{// If error is empty, success is achieved, there is no error console.log(data); } }) } try{read('./1.txt');
 }catch(e){
 console.log('err',e);
 };
Copy the code

When you visit a server, for example, to request an HTML page, such as a list of users. On the one hand, the server reads the template file, which may be ejS Pug Jade Handlebar, and on the other hand, it reads the data (which may be placed in the file or in the data), both of which are very slow and therefore asynchronous.

This demon pyramid has the following problems

    1. Very ugly
    1. Very difficult to maintain
    1. It’s inefficient because they’re serial
fs.readFile('./template.txt'.'utf8'.function (err, template) {
  fs.readFile('./data.txt'.'utf8'.function (err, data) {
    console.log(template + ' '+ data); })})Copy the code

How to solve this problem of nested callback

This is a class in the Node core module that allows you to create an instance of an event emitter. There are two core methods called on Emit. On means to register listening and emit means to emit events

let EventEmitter = require('events');
leteve = new EventEmitter(); // This HTML object holds the final datalethtml = {}; //template data // listen for the data fetch success event, and call the eve.on callback when the event occurs.'ready'.function(key,value){
  html[key] = value;
  if(Object.keys(html).length == 2){ console.log(html); }}); fs.readFile('./template.txt'.'utf8'.function(err, template) {//1 The event name 2 argument is followed by eve.emit('ready'.'template',template);
})
fs.readFile('./data.txt'.'utf8'.function (err, data) {
  eve.emit('ready'.'data',data); })*/ // handled by a sentry functionfunction done(key,value){
  html[key] = value;
  if(Object.keys(html).length == 2){ console.log(html); }}Copy the code

Many of ES6’s features are Generator related and can be used for a wide range of purposes, including any module that needs to be asynchronous, such as Ajax, Filesystem, or array object traversal. Generator functions differ from normal functions in two ways: function has an asterisk between the function name and function name, and function body uses yield expressions. Like this:

/ * * * generators is a function that can be used to generate an iterator * generator function is different from the ordinary function, general function is once the call must be performed among * but generator function can pause, can perform a rest for a while * / / / generator function has a characteristic, need to add a * / / generator has several stages, How do you divide these stages?function*go(a){ console.log(1); // This line implements the input and output, with the output placed after yield and the input before yieldlet b =  yield a;
    console.log(2);
    let c = yield b;
    console.log(3);
    returnc; } // A generator function is different from a normal function in that it does not execute immediately when called. // It returns an iterator to the generator, which is an object that returns a value object every time next is calledlet it = go("A value"); // Next does not need parameters for the first executionletr1 = it.next(); The first call to next returns an object with two properties: value (yield) and value (yield)doneIndicates whether the iteration completes console.log(r1); //{ value:'a'.done: false }
let r2 = it.next('B values'); console.log(r2); //{ value:'B values'.done: false }
let r3 = it.next('C values'); console.log(r3); //{ value:'C values'.done: true }
Copy the code

! The key to the

Let’s recall the asynchronous implementation of promise before, taking Bluebird as an example:

let Promise = require('bluebird');
let fs = require('fs');
function promisifyAll(obj) {
  for (let key in obj) {
    if (obj.hasOwnProperty(key) && typeof obj[key] == 'function') {
      obj[key+'Async'] = Promise.promisify(obj[key]); }}} // It will iterate over all the methods on the object and add a new method to each method Async promisifyAll(fs); fs.readFileAsync('./1.txt'.'utf8').then(data => console.log(data));
Copy the code

Now combine Generator and promise together:

let fs = require('fs');
function readFile(filename) {
 return new Promise(function (resolve, reject) {
   fs.readFile(filename, 'utf8'.function(err, data) { err ? reject(err) : resolve(data); }); })}function *read() {
 console.log('开始');
 let a = yield readFile('1.txt');
 console.log(a);
 let b = yield readFile('2.txt');
 console.log(b);
 let c = yield readFile('3.txt');
 console.log(c);
 return c;
}
function co(gen) {
 letit = gen(); // We want to keep our generator runningreturn new Promise(function (resolve, reject) {
   !function next(lastVal) {
       let {value,done} = it.next(lastVal);
       if(done){
         resolve(value);
       }else{ value.then(next,reject); }}} ()); } co(read).then(function (data) {
 console.log(data);
});
Copy the code

With the release of Node 7, more and more people are exploring async/await, which is said to be the ultimate solution for asynchronous programming

let Promise = require('bluebird');
let readFile = Promise.promisify(require('fs').readFile);
async function read() {//await must be followed by a promise,let a = await readFile('./1.txt'.'utf8');
  console.log(a);
  let b = await readFile('./2.txt'.'utf8');
  console.log(b);
  let c = await readFile('./3.txt'.'utf8');
  console.log(c);
  return 'ok';
}

read().then(data => {
  console.log(data);
});
Copy the code

Async await is syntactic candy and is implemented internally with generator+ Promise