async/await 如何通过同步的方式实现异步

来源: github.com/Advanced-Fr…

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;
  }
}

复制代码

image-20210603163246191

迭代器(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();

复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享