preface
The simple use of async and await will not be described here. Many front-end pain points can be solved by one or two keywords in ES6 and ES7, but are eventually converted into ES5 syntax by Babel in most cases.
As a daily CV front-end, I would like to know more about it. Maybe one day I can save an overnight
Chatter of the Generator
Relevant methods
Generator.prototype.next() returns a value generated by the yield expression
The Generator. The prototype. The return () returns the value of a given Generator and an end
The Generator. The prototype. Throw () to the Generator throw an error
Basic usage
function* gen() {
try {
let first = yield 1;
let second = yield first + 2;
yield second + 3;
} catch (e){
console.log(e); }}var iterator = gen();
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next(4)); // {value: 6, done: false}
console.log(iterator.next()); // {value: NaN, done: false}
console.log(iterator.next()); // {value: undefined, done: true}
console.log(iterator.return(); // { value: undefined, done: true }
console.log(iterator.return(1); // { value: 1, done: true }
iterator.throw('Wrong'); / / make a mistake
Copy the code
If you answered all of the above questions correctly, you have mastered the basics.
Object to… , the for of
A data structure that deploys the symbol. iterator attribute can use for… Go through with… Operator operation
Iterator Object does not have a Symbol. Iterator. This will cause an error when used directly
let obj = {
0: 'a'.1: 'b'.2: 'c',}for(let p of obj){
console.log(p);//TypeError: obj is not iterable
}
Copy the code
So you need to add a generator method on Object
console.log([ // ... Array.from. {0: 1.1: 2.2: 3.length: 3[Symbol.iterator]:function* (){
let index = 0;
while(index ! = =this.length){
yield this[index++]; }}// [Symbol.iterator]() {
// let len = this.length;
// let index = 0;
// // iterators have a next method and return value,done after the method is executed
// return {
// next: () => {
// return { value: this[index++], done: index === len + 1 };
/ /}
/ /};
/ /}}]);Copy the code
Regenerator converter
During the compilation phase, the corresponding abstract syntax tree (AST) needs to be processed to generate ES5 syntax structures that conform to the runtime code. In the runtime phase, runtime functions are added to assist the compiled statement execution.
The ReGenerator website provides visual operations. An example before and after simple AST transcoding is as follows:
function *range(max, step) {
var count = 0;
step = step || 1;
for (var i = 0; i < max; i += step) {
count++;
yield i;
}
return count;
}
var gen = range(20.3), info;
while(! (info = gen.next()).done) {console.log(info.value);
}
console.log("steps taken: " + info.value);
Copy the code
After the transformation
ar _marked =
/*#__PURE__*/
regeneratorRuntime.mark(range);
function range(max, step) {
var count, i;
return regeneratorRuntime.wrap(function range$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
count = 0;
step = step || 1;
i = 0;
case 3:
if(! (i < max)) { _context.next =10;
break;
}
count++;
_context.next = 7;
return i;
case 7:
i += step;
_context.next = 3;
break;
case 10:
return _context.abrupt("return", count);
case 11:
case "end":
return _context.stop();
}
}
}, _marked);
}
var gen = range(20.3),
info;
while(! (info = gen.next()).done) {console.log(info.value);
}
console.log("steps taken: " + info.value);
Copy the code
Excellent CO library to solve asynchronous problems before async and await
Co is an open source project launched by TJ in 2013 that uses ES6 Generator functions to solve asynchronous operations.
A key part
/**
* Execute the generator function or a generator
* and return a promise.
*
* @param {Function} fn
* @return {Promise}
* @api public* /
function co(gen) {
// Hold the context
var ctx = this;
// array.prototype. slice removes passed method names and leaves arguments
var args = slice.call(arguments.1);
// we wrap everything in a promise to avoid promise chaining,
// which leads to memory leak errors.
// see https://github.com/tj/co/issues/180
Co () returns a Promise object
return new Promise(function(resolve, reject) {
// Execute a Generator to get the traverser
if (typeof gen === 'function') gen = gen.apply(ctx, args);
if(! gen ||typeofgen.next ! = ='function') return resolve(gen);
// Execute the success callback
onFulfilled();
/ * * *@param {Mixed} res
* @return {Promise}
* @api private* /
function onFulfilled(res) {
var ret;
try {
ret = gen.next(res);
} catch (e) {
return reject(e);
}
next(ret);
return null;
}
/ * * *@param {Error} err
* @return {Promise}
* @api private* /
function onRejected(err) {
var ret;
try {
ret = gen.throw(err);
} catch (e) {
return reject(e);
}
next(ret);
}
/**
* Get the next value in the generator,
* return a promise.
*
* @param {Object} ret
* @return {Promise}
* @api private* /
// Execute next continuously
function next(ret) {
// Generator completed
if (ret.done) return resolve(ret.value);
// Each time the yield value is converted to a promise
var value = toPromise.call(ctx, ret.value);
// call consecutively with promise.then
// Onpity, onRejected will continue to call next itself
if (value && isPromise(value)) return value.then(onFulfilled, onRejected);
// Yield cannot be converted to promise
return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, '
+ 'but the following object was passed: "' + String(ret.value) + '"')); }}); }Copy the code
async,await
What are async,await functions? In short, it is the syntactic sugar of Generator functions.
Reference documentation
Syntax for Generator functions
Asynchronous application of Generator functions
Async function