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