• 作者:老汪软件技巧
  • 发表时间:2024-11-14 21:01
  • 浏览量:

ES7 - Async / Await

Async和Await是ES7中提出对异步操作的解决方案,也有说Async和Await是Generator的语法糖

// 模拟异步操作;
function sayHi(name) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('hi', name);
      resolve()
    })
  })
}
async function getPeople() {
  await sayHi('Bob');
  await sayHi('Flank')
}

ES6 - Generator

Generator是ES6提出的一种异步编程的解决方案, 如果用Generator来实现异步操作

如果对Generator语法不清楚的可以了解阮一峰 ECMAScript 6 (ES6) 标准入门教程 第三版,主要就是函数形态上有*,通过yield来定义不同的状态,并且返回一个迭代器对象;

function sayHi(name) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('hi', name);
      resolve()
    })
  })
}
function* getPeople() {
  yield  sayHi('Bob');
  yield sayHi('Flank');
  return 'ending';
}
var hw = getPeople();
// 返回一个迭代器对象
hw.next()
// { value: Promise, done: false }
hw.next()
// { value: Promise, done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }

ES5 - regeneratorRuntime

如果需要考虑到浏览器的兼容性,对ES6语法的兼容,我们也可以采用babel转译该语法向下兼容转换成ES5的语法

转换后语法

function sayHi(name) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      console.log('hi', name);
      resolve();
    });
  });
}
function getPeople() {
  return regeneratorRuntime.async(function getPeople$(_context) {
    while (1) {
      switch (_context.prev = _context.next) {
        case 0:
          _context.next = 2;

_Async和Await是ES7中提出对异步操作的解决方案,也有说Async和Await是Generator的语法糖_Async和Await是ES7中提出对异步操作的解决方案,也有说Async和Await是Generator的语法糖

return regeneratorRuntime.awrap(sayHi('Bob')); case 2: _context.next = 4; return regeneratorRuntime.awrap(sayHi('Flank')); case 4: case "end": return _context.stop(); } } }, null, null, null, Promise); }

可以看到其中的关键的函数regeneratorRuntime, regeneratorRuntime 是facebook regenerator库提供的API,主要用来将基于 ES6 generator 和 async/await 的代码转换成 ES5 兼容的代码;

regeneratorRuntime原理, regeneratorRuntime中async函数的原理,是上下文保存,每次执行yield的时候,都执行一遍包装的函数,用context来维护上下文;

下面实现一个简单的regeneratorRuntime

// 全局维护context对象来存储函数执行的上下文;
const Context = {
  next: 0,
  prev: 0,
  done: false,
  stop: () => {
    this.done = true;
  }
}
// gen函数用来封装yield的不同函数的执行
function gen(context) {
  while (1) {
    switch (context.prev = context.next) {
      case 0:
        debugger
        context.next = 2;
        return sayHi('Bob');
      case 2:
        context.next = 4;
        return sayHi('Flank');
      case 4:
        context.stop();
        return undefined
    }
  }
}
// 定义next(),进行迭代器的一个执行;
let getPeople = function () {
    return {
        next: function () {
            value = gen$Context);
            done = Context.done
            return {
                value,
                done
            }
        }
    }
}