We found that Promise solved the asynchronous programming problem, but it was still not elegant enough, and we wanted to write asynchronous code as succinctly as synchronous code.

1.Generator

  • When you’re executing a function, you can get at some pointStop functionAnd do some other work, and then return to this function to continue, or evenCarry some new values“, and continue to execute.
  • The scenario described above is exactly the kind of problem that JavaScript generator functions aim to solve. When we call a generator function, it does not execute immediately, but requires usManually perform the iteration(Next method). That is, you call a generator function and it returns you an iterator. The iterator iterates over each breakpoint.
  • The value attribute of the return value of the next method is the Generator function that outputs data; The next method can also accept arguments, which input data into the body of the Generator function

1.1 Generator With Promise

let fs = require('fs');
function read(file){
    return new Promise(function(resolve,reject){
        fs.readFile(file,'utf8'.function(err,data){
            if(err) returnreject(err); resolve(data); })})}function*gen(filename){// the first time it.next(). Value is the promise after yieldlet a = yield read(filename);
    let b = yield read(a);
    return b;
}
let it = gen('./1.txt'); // This returns an iterator (an iterator returns an object with value anddoneProperty when the iteration is completedoneThe properties of the astrue)
it.next().value.then(function(data){
    it.next(data).value.then(function(value){ console.log(it.next(value).value); })})Copy the code

Here we found manual iteration quite complex, so there is one library that works with the Generator, our CO library.

1.2 Applying the CO Library

function *gen(filename){
    let a = yield read(filename);
    let b = yield read(a);
    return b;
}
let co = require('co');
co(gen('./1.txt')).then(function(data){
    console.log(data);
},function(err){
    console.log(err)
})
Copy the code

The CO library will help us do automatic iteration. Eliminates the need for manual iteration

1.3 Simulating CO library

function co(gen){
    return new Promise(function(resolve,reject){
        let it = gen;
        functionNext (data){// Pass the last result in the next iterationlet {value,done} = it.next(data);
            if(!done){
                value.then(function(data){ next(data); // Continue iterating if not finished},reject)}else{
                resolve(data);
            }
        }
        next()
    });
}
Copy the code

2.async/await

Async and await are syntactic sugars for generator and CO, and with the async keyword you can easily do what you used to do with generator and CO functions

let fs = require('fs');
function read(file){
    return new Promise(function(resolve,reject){
        fs.readFile(file,'utf8'.function(err,data){
            if(err) return reject(err);
            resolve(data);
        })
    })
}
async function gen(filename){
    let a = await read(filename);
    let b = await read(a);
    return b;
}
gen('./1.txt').then(function(data){
    console.log(data)
},function(err){
    console.log(err);
});

Copy the code

We found that both generator and async/await are dependent on promises, and we are introducing several promise libraries.

3. Q library

Q is a module that implements promises in Javascript

let fs = require('fs');
let Q = require('q');
function read() {letdefer = Q.defer(); // Our delay object fs.readfile ('1.txt'.'utf8'.function(err,data){
        if(err) return defer.reject(err);
        defer.resolve(data);
    });
    return defer.promise;
}
read().then(function(data){
    console.log(data); 
},function(err){
    console.log(err);
});
Copy the code

3.1 Q.a ll method

Consistent with usage in promise.all

let fs = require('fs');
let Q = require('q');
function read(filename){
    letdefer = Q.defer(); // Our delay object fs.readfile (filename,'utf8'.function(err,data){
        if(err) return defer.reject(err);
        defer.resolve(data);
    });
    return defer.promise;
}

Q.all([read('./1.txt'),read('./2.txt')]).then(function([a,b]){ console.log(a,b) }); Q.a. ([q.A. ([read('./1.txt'),read('./2.txt')]).spread(function(a,b){
    console.log(a,b)
})
Copy the code

3.2 Q.f call

You can create promises with Q.fcall

let fs = require('fs');
let Q = require('q');
Q.fcall(function() {return 100;
}).then(function(data){
    console.log('result',data)
},function(err){
    console.log(err)
})
Copy the code

4.blueBird

There are two commonly used methods in blueBird called Promisify and promisifyAll

let fs = require('fs');
let blueBird = require('bluebird');
let read = blueBird.promisify(fs.readFile);

read('./1.txt'.'utf8').then(function(data){
    console.log(data)
},function(err){ console.log(err) }); // Asynchronous methods can be promisingly used, as well as all methods, with Async suffixed after passing promisifyAlllet fs = require('fs');
let blueBird = require('bluebird');
blueBird.promisifyAll(fs);
fs.readFileAsync('./1.txt'.'utf8').then(function(data){
    console.log(data)
},function(err){
    console.log(err)
});

Copy the code

Node has also implemented the promisify method in the Util module.

4.1 implementation bluebird

function promisify(fn) {
    return function(... args) {return new Promise(function(resolve, reject) { fn.call(null, ... args,function (err, data) {
                if (err) returnreject(err); resolve(data); }}})})function promisifyAll(obj){
    Object.keys(obj).forEach(item=>{
        if(typeof obj[item] === 'function'){
            obj[item+'Async'] = promisify(obj[item])
        }
    });
}
Copy the code

Can’t wait to see how the promise comes true? In the next section, we come to the implementation principle of Promise, like a like it! Give me a tip if you support me!