1 the asynchronous
- “Asynchronous” simply means that a task is divided into two parts, the first part is performed, then the other part is performed, and when you are ready, the second part is performed. For example, if a task is to read a file for processing, the asynchronous execution process is as follows.
This discontinuous execution is called asynchrony. Accordingly, continuous execution is called synchronization.
2 higher order functions
Functions, as first-class citizens, can be used as arguments and return values, or as arguments to functions
2.1 Can be used to generate functions in batches
// Determine if an argument is a string
function isString(param){
return Object.prototype.toString.call(param) == '[object String]';
}
isString(123);
// Check whether an argument is an array
function isArray(param){
return Object.prototype.toString.call(param) == '[object Array]';
}
isArray([]);
Copy the code
A function can be a return value
function isType(type){
return function(param){
return Object.prototype.toString.call(param) == `[object ${type}] `; }}let isString = isType('String');
let isArray = isType('Array');
console.log(isString({}))
console.log(isArray([]))
Copy the code
2.2 Can be used for functions that need to be called more than once
A function can be passed as an argument to another function
function eat(){
console.log("Finished")}// Let him execute several times before executing
function after(times,fn){
let count = 0;
return function(){
if(count++==times){ fn(); }}}let newEat = after(3,eat);
newEat();
newEat();
newEat();
Copy the code
3. The syntactic goal of asynchronous programming is to make it more like synchronous programming
- Callback function implementation
- Event listeners
- Release subscription
- Promise/A+ and generator functions
- async/await
4. The callback
Let’s say I’m going to read a file, asynchronously
let fs = require('fs');
fs.readFile('./1.txt'.'utf8'.function(err,data){
if(err){ // If err has a value, the program is in error
console.log(err);
}else{ // If err is empty, success with no errors
console.log(data); }});Copy the code
The problem with callback functions
- Failed to catch an error try catch return
- Can’t return
- The callback hell
function read(filename){
fs.readFile(filename,'utf8'.function(err,data){
if(err){ // If err has a value, the program is in error
console.log(err);
}else{ // If err is empty, success with no errors
console.log(data); }}); }try{
read('1.txt');
}catch(e){
console.log(e);
}
console.log(2);
Copy the code
When you visit the server, for example, to request an HTML page, such as a list of users. The server reads template files on the one hand, which can be EJS, PUG, JADE, handlebar, and data on the other (which can be placed in files or data), both of which are very slow, so they are asynchronous.
- This is an ugly way to write it
- Very difficult to maintain
- It’s inefficient because it’s 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
6. Asynchronous process solutions
6.1 Through event publishing subscription
// This is a class in the Node core module, through which you can pass an instance of the time emitter, which has two core methods
// On emit,on means to register listener, and emit means to emit event
let EventEmitter = require('events');
let eve = new EventEmitter();
// This HTML object is stored
let html = {}; // template data
// Listen for a data acquisition success event and call the callback function when the event occurs
eve.on('ready'.function(key,value){
html[key] = value;
if(Object.key(html).lenght==2) {console.log(html);
}
})
fs.readFile('./template.txt'.'utf8'.function(err,template){
// the event name 2 argument is passed to the callback function
eve.emit('ready'.'template',template);
})
fs.readFile('./data.txt'.'utf8'.function(err,data){
//
eve.emit('ready'.'data',data);
})
Copy the code
6.2 Sentry Variables
// Use a sentinel to solve the problem
let html = {}
function done(key,value){
html[key]=value;
if(Object.keys(html).length===2) {console.log(html); }}; fs.readFile('./template.txt'.'utf8'.function(err,template){
done("template",data)
})
fs.readFile('./data.txt'.'utf8'.function(err,data){
done("data",data)
})
Copy the code
// Use a sentinel to solve the problem
let html = {}
function render(lenght,cb){
let html = {};
if(Object.keys(html).length===lenght){ cb(html); }}let done = render(2.function(html){
console.log(html);
});
fs.readFile('./template.txt'.'utf8'.function(err,template){
done("template",data)
})
fs.readFile('./data.txt'.'utf8'.function(err,data){
done("data",data)
})
Copy the code
6.4 Generator Generators/ yield
A generator is a function that you can use to generate iterators. A generator function is different from a normal function, where once you call a generator function, it will always run out of time but a generator function can run in between, it can run in between
The yield defines the value returned from the generator function via the iterator protocol. If omitted, undefined is returned.
function *go(params) {
console.log(1);
// where b is to provide external input
// This line implements input and output, with output placed after yield and input before yield
let b = yield 'a';
console.log(2);
let c = yield b;
console.log(3);
return c;
}
// Generator functions are different from normal functions in that when called, the function is not executed immediately
// It returns the generator's iterator, which is an object that returns a value object every time next is called
let it = go();;
let r1 = it.next();
// The first call to next returns an object with two properties, value for yield and done for iteration completion
console.log(r1); //{value:'a',done:false};
// Next does not need to pass parameters for the first time
let r2 = it.next('B values');// Pass to b
console.log(r2); // {value:'a',done:false};
let r3 = it.next();// {value:undefined,done:true};
console.log(r3);
Copy the code
6.5 Promise to handle
A Promise object is a proxy object (proxy for a value), and the proxied value may not be known at the time the Promise object is created. It allows you to bind handlers for success and failure of asynchronous operations.
6.5.1 example
let p1 = new Promise((resolve, reject) = > {
setTimeout((a)= > {
resolve(1000)},1000);
});
p1.then(res= >{
console.log(res)
})
Copy the code
Tactical fix packs for 6.5.2 promise. All
It receives an array of promises, and if the promise completes all of these, the promise succeeds, and if one fails, the whole thing fails
When multiple data requests are made asynchronously, all is used
let p1 = new Promise((resolve, reject) = > {
setTimeout((a)= > {
resolve(1000)},1000);
});
let p2 = new Promise((resolve, reject) = > {
setTimeout((a)= > {
resolve(1000)},1000);
});
Promise.all([p1,p2]).then(res= >{
console.log('= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =');
console.log(res);
console.log('= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =');
},err=>{
console.log('= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =');
console.log(err);
console.log('= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =');
})
Copy the code
The principle of
function gen(times,cb) {
let result = [],count=0
return function(i,data){
result[i] = data;
if(++count == times) { cb(result); }}}Promise.alls = function (promises) {
return new Promise(function (resovle, reject) {
let result = []
let count =0
let done = gen(promises.length,resovle)
// function done(i,data){
// result[i] = data;
// if (++count== promises.length) {
// resovle(result)
/ /}
// }
for (let i = 0; i < promises.length; i++) {
// promises[i].then(done.bind(null,i));
promises[i].then(function (data) { done(i,data) }, reject); }})}Promise.alls([p1,p2]).then(res= >{
console.log('= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =');
console.log(res);
console.log('= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =');
},error=>{
console.log('= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =');
console.log(error);
console.log('= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =');
})
Copy the code
6.5.3 promise. Race
You receive an array of promises, and if you get one success, you’re successful, and if you get one failure, you’re failed
When you have three unstable ports, but you can request all three ports at the same time, the one who comes back first uses the one
let p1 = new Promise((resolve, reject) = > {
setTimeout((a)= > {
resolve(1000)},1000);
});
let p2 = new Promise((resolve, reject) = > {
setTimeout((a)= > {
resolve(1000)},1000);
});
Promise.race([p1,p2]).then(res= >{
console.log('= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =');
console.log(res);
console.log('= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =');
})
Copy the code
The principle of
Promise.race = function (promises) {
return new Promise(function (resovle, reject) {
for (let i = 0; i < promises.length; i++) { promises[i].then(resovle, reject); }})}Copy the code
6.6 Co
Co is a generator-based flow control tool for Node.js and browsers. With Promise, you can write non-blocking code in a more elegant way.
let fs = require('fs');
function readFile(filename) {
return new Promise(function (resolve, reject) {
fs.readFile(filename, function (err, data) {
if (err)
reject(err);
elseresolve(data); })})}function *read() {
let template = yield readFile('./template.txt');
let data = yield readFile('./data.txt');
return template + '+' + data;
}
co(read).then(function (data) {
console.log(data);
}, function (err) {
console.log(err);
});
Copy the code
function co(gen) {
let it = gen();
return new Promise(function (resolve, reject) {!function next(lastVal) {
let {value, done} = it.next(lastVal);
if (done) {
resolve(value);
} else {
value.then(next, reason => reject(reason));
}
}();
});
}
Copy the code
6.7 Async/await
With the async keyword, you can easily do what you used to do with generators and co functions but it’s really just the generator+ Promise syntax
The advantages of Async
- Built-in actuator
- Better semantics
- Wider applicability
async function timeout() {
return 'hello world'
}
timeout().then(res= >{
console.log(res);
})
console.log('I'll do it later, but I'll do it first.');
Copy the code
Async returns a promise
Let me give you an example
function loading(num) {
return new Promise((resolve, reject) = > {
setTimeout((a)= > {
resolve(2 * num)
}, 2000); })}// This is a function constructor
Copy the code
I want to pass in three values 30, 50, and 40 and sum them up. The delay time simulates the network request time
async function testResult() {
let one = await loading(30);
let two = await loading(50);
let three = await loading(40);
console.log(one + two + three);
}
testResult();
Copy the code