async/await原理

JS异步编程方法

  • 最开始使用回调形式
setTimeout(callback, 1000)
  • 回调形式容易形成回调地狱,故es6发明了promise,采用链式回调的方式
const test = new Promise();
test.then(cb1).then(cb2);
  • 链式回调虽然更加直观了,但仍是要将函数经过then传递,更为理想的方式是,用同步的写法去写异步逻辑,因而es7给出了async和await关键字
const p1 = () => { return new Promise((res) => {
    setTimout(() => {
        console.log('p1');
        res(2);
    }, 1000);
})};
const p = async () => {
    const p2 = await p1();
    console.log(p2);
}
// 输出 p1 2
  • 因而可知,async和await处理异步是基于promise的,await后面须要跟一个promise(一般是一个返回promise的函数,跟在await后面并执行),若是不跟promise也不会报错,会视做普通同步函数执行。
  • async/await是语法糖,用async标记的函数,在其内部遇到await标记的逻辑时,会暂时返回,不执行后续的逻辑,等await内部的逻辑处理完毕后,再继续走await后面的逻辑,这个方式,其实就是es6定义的generator函数。即async与await将标记的函数转换成了生成器。

原理

  • 将p变成一个generator函数,其中遇到await的地方就改写成yield:
function* p () {
    const p2 = yield p1();
    console.log(p2)
}
  • 咱们能够运行p(),获得一个迭代器,调用迭代器的next(),执行下一步,但这种方式须要手动调用next才会继续执行函数p,因此咱们就须要一个自动执行这个函数的函数asyncFunc:
asyncFunc(generator) {
    const gen = generator();
    function next(data) {
        const { value, done } = gen.next(data);
        if (done) {
            return value;
        } else if (!(value instanceof Promise)) {
            next(value);
        } else {
            value.then((data) => next(data));
        }
    }
    next();
}
asyncFunc(p);
  • 经过调用asyncFunc(p),咱们执行了生成器p,获得迭代器gen,经过递归next方法,将gen自动执行到底(即done = true时,每次调用迭代器的next,都会返回value和done标志,value是yield后面表达式的值);
  • 而当yield后面表达式返回一个promise时,经过将迭代器的next方法放到pormise的then中执行,使得yield后面的逻辑要等待p1完成后才继续进行,即达到同步的效果
  • 可见async/await是经过将函数变为一个生成器函数,并使用自动执行函数来执行他,在执行过程当中,有意地让生成的迭代器放到promise的then中,即异步完成后才执行,从而达到的同步效果。
  • 完整流程以下:
const p1 = () => { return new Promise((res) => {
    setTimout(() => {
        console.log('p1');
        res(2);
    }, 1000);
})};

function* p () {
    const p2 = yield p1();
    console.log(p2)
}

asyncFunc(generator) {
    const gen = generator();
    function next(data) {
        const { value, done } = gen.next(data);
        if (done) {
            return value;
        } else if (!(value instanceof Promise)) {
            next(value);
        } else {
            value.then((data) => next(data));
        }
    }
    next();
}
asyncFunc(p);
  • 首先自动执行函数asyncFunc执行生成器p获得迭代器gen
  • 调用next函数,执行gen.next,这时迭代器执行到p函数的yield p1(),返回一个promise,该promise一秒后将打印'p1',并返回2
  • 在此以前,自执行函数,在该promise的回调中传入了next方法
  • 则一秒后,打印'p1',返回2,执行next(2)
  • 则迭代器执行yield p1()后面的逻辑,而且,把2赋给了p2(generator语法如此)
  • 打印'2'
  • async/await的实现要比上述的复杂,但核心逻辑就是generator结合自执行函数。
相关文章
相关标签/搜索