Let’s look at the following code execution results:

const funA = () => {
    console.log('funA-1')
    const p = new Promise((resolve) => {
        resolve('funA-2')
    })
    console.log('funA-3')
    return p
}

const funB = () => {
    console.log('funB-1')
    return 'funB-2'
}

const funB2 = () => {
    console.log('funB2-1')
    return 'funB2-2'
}

const funC = async () => {
    console.log('funC-1')

    const p = await funA()
    console.log(p)

    console.log('funC-2')

    const b = await funB()
    console.log(b)

    console.log('funC-3')

    const b2 = await funB2()
    console.log(b2)

    console.log('funC-4')

}

console.log('start')
funC()
console.log('end')
Copy the code

Note that funa-2 is followed by end

That is, after performing the microtask to the right of the await, the unfinished synchronization task in the scope that calls the outer function will be performed first

To understand the internal implementation of async await, you must first understand generator functions

function  * gen(x) {
    console.log('111111')
    const a = 5
    const b = yield a * 2
    console.log('-----b: ', b)
    const c = yield x - 1
    console.log('-----c: ', c)
    return b
}

const g = gen(1)
console.log(g)
console.log(g.next())
console.log(g.next())
console.log(g.next(8))
console.log(g.next(6))
console.log(g.next())
Copy the code

  • Instead of executing immediately, gen() pauses and returns an Iterator (see the Iterator Iterator).
  • Each time g.ext () breaks the pause state and executes until the next yield or return is reached
  • When yield is encountered, the expression after Yeild is executed and the value is returned, and the state is paused again, done: false.
  • The next function can take parameters, which are received by variables in the function body, as the return result of the asynchronous task in the previous phase
  • When a return is encountered, the value is returned and the execution ends, that is, done: true
  • Every time g.ext () returns {value:… , done: … } in the form of

Difference between async/await and Generator:

  • Async /await comes with an executor that automatically executes the next step without manually calling next()
  • Async functions return a Promise object, while Generator returns a Generator object
  • Await can return the resolve/reject value of a Promise

Async /await is a generator with an executor that calls next if Promise fails then and resolve if Promise fails.

Jane’s version:

Function run(gen) {var g = gen(); function next(val) {function run(gen) {var g = gen(); G.ext () var res = g.ext (val) If (res.done) return res.value then(val => {//Promise's then method is a precondition for automatic iteration. _next(val) // Wait for the Promise to complete, automatically execute the next, and pass in the value of resolve})} _next()Copy the code

Perform:

function* myGenerator() {
  console.log(yield Promise.resolve(1))   //1
  console.log(yield Promise.resolve(2))   //2
  console.log(yield Promise.resolve(3))   //3
}

run(myGenerator)
Copy the code

Extension: Add base types; Add error handling

Function run(gen) {return new promise ((resolve, resolve); Reject) => {var g = gen() function _next(val) {var res = g.ext (val)} catch(err) {return reject(err); } if(res.done) { return resolve(res.value); Promise. Resolve (res.value). Then (val => {_next(val); }, err => {// throw error g.row (err)}); } _next(); }); }Copy the code

Babel:

// this is equivalent to our run() function _asyncToGenerator(fn) {// return a function, as async. Our run executes Generator directly, Return function() {var self = this var args = arguments return new Promise(function(resolve, arguments)) reject) { var gen = fn.apply(self, args); Function _next(value) {asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'next', value); asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'next', value); } function _throw(err) {asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'throw', err); } _next(undefined); }); }; } function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); }}Copy the code

Reference:

Zhuanlan.zhihu.com/p/115112361 segmentfault.com/a/119000002…