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联合自执行函数。