async/await是参照generator封装的一套异步处理方案,可以理解为generator的语法糖,async/await关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise
生成器对象(generator)是由一个generator function返回,并它符合可迭代协议和迭代器协议
要成为可迭代对象,一个对象必须实现 @@iterator 方法
而iterator的思想来源于单项链表
链表
链表是一组节点组成的集合,每个节点都使用一个对象的引用来指向它的后一个节点。
链表相较于数组来说,链表不需要连续的内存空间,它是由一组零散的内存块透过指针连接而成,所以,每一个块中必须包含当前节点内容以及后继指针,常见的链表有单链表、双链表以及循环链表
class LinkNode{
constructor(ele,next){
this.ele = ele
this.next = next
}
}
class linkList{
constructor(){
this.head = new LinkNode('head')
}
append(element){
let newNode = new LinkNode(element)
let currentNode = this.findLast()
currentNode.next = newNode
}
findLast(){
let currNode = this.head;
while (currNode.next) {
currNode = currNode.next;
}
return currNode;
}
}
复制代码
迭代器(iterator)
Symbol.iterator 为每一个对象定义了默认的迭代器。该迭代器可以被 for…of 循环使用
该方法返回具有两个属性的对象:value:系列中的next值和done
function makeRangeIterator(start=0,end=Infinity,step=1){
let nextIndex = start
let iterationCount = 0
const rengeIterator = {
next: function(){
let result
if(nextIndex < end){
result = {value: nextIndex, done:false}
nextIndex += step
iterationCount ++
return result
}
return {value: iterationCount, done: true}
}
}
return rengeIterator
}
let it = makeRangeIterator(1, 10, 2);
let result = it.next();
while (!result.done) {
console.log(result.value); // 1 3 5 7 9
result = it.next();
}
console.log("Iterated over sequence of size: ", result.value); // 5
复制代码
生成器(Generator)
生成器对象是生成器函数(GeneratorFunction)返回的,它符合可迭代协议和迭代器协议,既是迭代器也是可迭代对象,可以调用next方法,但它不是函数,更不是构造函数
function* name(param[param]){statements}
调用一个生成器函数并不会马上执行它里面的语句,而是返回一个这个生成器的迭代器对象,当这个迭代器的next()方法被首次(后续)调用时,其内的语句会执行到第一个(后续)出现yield的位置为止(让执行处于暂停状态),yield后紧跟迭代器要返回的值,或者如果用的是yield*,则表示将执行权移交给另一个生成器函数(当前生成器暂停执行),调用 next() (再启动)方法时,如果传入了参数,那么这个参数会作为上一条执行的 yield 语句的返回值
function* idMaker(){
let index = 0;
while(true)
yield index++;
}
let gen = idMaker(); // "Generator { }"
console.log(gen.next().value);
// 0
console.log(gen.next().value);
// 1
console.log(gen.next().value);
// 2
复制代码
Generator处理异步与callback
如何处理异步呢?其实二者没有任何关系,我们只是通过一些方式强行的它们产生了关系,才会有 Generator 处理异步
const promisify = require('util').promisify
const path = require('path')
const fs = require('fs')
const readFile = promisify(fs.readFile)
const gen = function*(){
const res1 = yield readFile(path.resolve(__dirname,'./a.json'))
const res2 = yield readFile(path.resolve(__dirname,'./b.json'))
}
const g = gen()
const g1=g.next()
g1.value.then(res1 => {
const g2 = g.next()
})
function run(gen) {
const g = gen();
function next(data) {
const res = g.next(data);
// 深度递归,只要 `Generator` 函数还没执行到最后一步,`next` 函数就调用自身
if (res.done) return res.value;
res.value.then(function(data) {
next(data);
});
}
next();
}
run(function*() {
const res1 = yield readFile(path.resolve(__dirname, '../data/a.json'), { encoding: 'utf8' });
console.log(res1);
// {
// "a": 1
// }
const res2 = yield readFile(path.resolve(__dirname, '../data/b.json'), { encoding: 'utf8' });
console.log(res2);
// {
// "b": 2
// }
});
复制代码
Async/Await
// Generator
run(function*() {
const res1 = yield readFile(path.resolve(__dirname, '../data/a.json'), { encoding: 'utf8' });
console.log(res1);
const res2 = yield readFile(path.resolve(__dirname, '../data/b.json'), { encoding: 'utf8' });
console.log(res2);
});
// async/await
const readFile = async ()=>{
const res1 = await readFile(path.resolve(__dirname, '../data/a.json'), { encoding: 'utf8' });
console.log(res1);
const res2 = await readFile(path.resolve(__dirname, '../data/b.json'), { encoding: 'utf8' });
console.log(res2);
return 'done';
}
const res = readFile();
复制代码