深入解析:为什么async/await被称为Generator函数的语法糖

作者:闭包旅人

时间:2026-10-23

浏览:192

本文深入解析JavaScript中async/await与Generator函数的关系,论证前者是后者的语法糖。通过对比使用async/await实现sleep功能与将其转换为Generator配合Promise自执行器的代码,揭示其底层执行原理及Babel转译的大致逻辑。

文章目录

async/await与Generator的关系概述

在阮一峰的ES6入门教程中,关于async函数的介绍指出:

async函数本质上就是Generator函数的语法糖。

那么,为何会有这样的说法呢?

首先,假设存在一个异步操作,我们可以利用async/await语法以同步代码的形式来模拟异步执行过程。

代码实现与原理转换

下面演示如何使用async/await来实现一个sleep(睡眠)功能。


function sleep(time) {
 return new Promise((resolve, reject) => {
 setTimeout(() => {
  resolve(1);
 }, time);
 });
}

async function test () {
 for(let i = 0; i < 10; i++) {
 let result = await sleep(1000);
 console.log(result);
 }
}

接下来,我们将上述async/await代码转换为使用Generator函数和Promise来实现的方式。


let test = function () {
 // ret 为一个Promise对象,因为ES6语法规定 async 函数的返回值必须是一个 promise 对象
 let ret = _asyncToGenerator(function* () {
 for (let i = 0; i < 10; i++) {
  let result = yield sleep(1000);
  console.log(result);
 }
 });
 return ret;
}();

// generator 自执行器
function _asyncToGenerator(genFn) {
 return new Promise((resolve, reject) => {
 let gen = genFn();
 function step(key, arg) {
  let info = {};
  try {
  info = gen[key](arg);
  } catch (error) {
  reject(error);
  return;
  }
  if (info.done) {
  resolve(info.value);
  } else {
  return Promise.resolve(info.value).then((v) => {
   return step('next', v);
  }, (error) => {
   return step('throw', error);
  });
  }
 }
 step('next');
 });
}

观察以上代码,逻辑是否变得清晰可见?将async/await改写为Generator的关键,在于利用Promise实现一个Generator的自执行器。Babel编译器的内部原理与此大致相同。

总结

以上就是本文的全部内容,希望这些内容对大家的JavaScript学习或工作有所参考,感谢支持。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章