欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

async函数的实现原理+实例

程序员文章站 2022-06-12 22:42:42
...

知识基础,了解generator的用法

// generator是实现async函数的关键
function* helloWorldGenerator() {
  yield '1';
  yield '2';
  return 'ending';
}

var hw = helloWorldGenerator();
hw.next()
// { value: '1', done: false }

hw.next()
// { value: '2', done: false }

hw.next()
// { value: 'ending', done: true }

hw.next()
// { value: undefined, done: true }
复制代码

案例

let fs = require('fs');
function readFile(filename) {
    return new Promise(function (resolve, reject) {
        fs.readFile(filename, function (err, data) {
            if (err)
                reject(err);
            else
                resolve(data);
        })
    })
}
function* read() {
    let template = yield readFile('./template.txt');
    let data = yield readFile('./data.txt');
    return template + '+' + data;
}
co(read).then(function (data) {
    console.log(data);
}, function (err) {
    console.log(err);
});
复制代码

解析

这里需要注意的是co函数的实现(如下),co函数是用来模拟async的关键

function co(gen) {
  // 初始化迭代器
  let it = gen();
  return new Promise(function (resolve, reject) {
     // 递归调用next,确保yeild后面的内容依次全部执行
    !function next(lastVal) {
      let {value, done} = it.next(lastVal);
      if (done) {
        resolve(value);
      } else {
        // 每次yield 的值,会作为next函数的参数
        // 所以上面的例子 let template = yield readFile('./template.txt') ,template就是yeild表达式返回的值
        value.then(next, reason => reject(reason));
      }
    }();
  });
}
复制代码

补充

// async 函数的实现,就是将 Generator 函数和自动执行器,包装在一个函数里。
async function read() {
  let template = await readFile('./template.txt');
  let data = await readFile('./data.txt');
  return template + '+' + data;
}

// 等同于
function read(){
  return co(function*() {
    let template = yield readFile('./template.txt');
    let data = yield readFile('./data.txt');
    return template + '+' + data;
  });
}
复制代码