ES12 中的 Generator 方法

ES12 (也称为 JavaScript 2021) 引入了一种新的处理异步编程的方法 - Generator 方法。Generator 方法可以让我们更简洁、更清晰地处理异步流程,避免了使用回调函数和 Promise 时可能出现的回调地狱或 Promise 嵌套的情况。本文将详细介绍 Generator 方法的使用和实现原理。

什么是 Generator 方法

Generator 方法是一种特殊的 JavaScript 函数,它可以在函数执行时控制函数的执行流程。Generator 方法通过 yield 关键字暂停函数执行,并提供一个返回值给调用者。调用者可以通过 next 方法恢复函数执行,并向函数传递参数。Generator 方法返回一个迭代器对象,可以使用 for of 循环迭代它的返回值。

下面是一个简单的 Generator 方法示例代码:

function* myGenerator() {
  yield 1;
  yield 2;
  yield 3;
}

const iterator = myGenerator();
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

上面的代码定义了一个名为 myGenerator 的 Generator 方法,它通过 yield 关键字返回三个值 1、2 和 3。我们可以通过调用 myGenerator() 获取一个迭代器对象 iterator,然后使用 iterator.next() 方法迭代三个返回值。最后一次调用 iterator.next() 将返回一个 done 属性为 true 的对象,表示迭代已经完成。

使用 Generator 方法处理异步流程

Generator 方法的真正威力体现在它可以提供一种完全不同的异步编程方式。我们可以将异步任务的处理步骤写成多个 yield 语句,通过调用 next 方法的方式逐步执行异步任务的不同环节。

下面是一个使用 Generator 方法处理异步流程的示例代码:

function fetchData(url) {
  return fetch(url).then(response => response.json());
}

function* myGenerator() {
  const user = yield fetchData("https://api.github.com/users/octocat");
  const repos = yield fetchData(`https://api.github.com/users/${user.login}/repos`);
  const firstRepo = repos[0];
  yield fetchData(`https://api.github.com/repos/${user.login}/${firstRepo.name}/readme`);
}

const iterator = myGenerator();
const userPromise = iterator.next().value;
userPromise.then(user => {
  const reposPromise = iterator.next(user).value;
  reposPromise.then(repos => {
    const readmePromise = iterator.next(repos).value;
    readmePromise.then(readme => {
      console.log(readme);
    });
  });
});

上面的代码定义了一个名为 myGenerator 的 Generator 方法,它通过 yield 关键字执行三个异步任务:获取 GitHub 用户 octocat 的信息、获取 octocat 的第一个仓库信息、获取仓库 octocat/Hello-World 的 README 内容。我们可以通过在迭代器上多次调用 next 方法依次运行这三个任务,并使用 Promise 的链式调用方式获取迭代器的返回值。

使用 Generator 方法可以使得异步代码更加清晰、简短,避免了使用回调函数和 Promise 时可能出现的回调地狱或 Promise 嵌套的情况。

实现 Generator 方法的原理

Generator 方法的工作原理很有趣。当我们调用 Generator 方法时,它并不会立即运行函数体内的代码。相反,它返回了一个迭代器对象,我们可以逐次运行函数体内的代码。

每次调用迭代器对象的 next 方法时,相应的代码段会开始运行,直到执行到下一个 yield 语句。在 yield 语句处,函数体会暂停执行,等待下一次的 next 方法调用恢复执行。通过这种方式,我们可以用迭代器生成器的方式,实现异步代码的流程控制。

下面的代码是一个简单的 Generator 方法的实现:

function* myGenerator() {
  console.log("start");
  yield 1;
  console.log("middle");
  yield 2;
  console.log("end");
}

const iterator = myGenerator();
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

上面的代码定义了一个 Generator 方法 myGenerator,它通过 yield 语句控制函数执行流程。我们可以通过调用 myGenerator() 获取一个迭代器对象 iterator,然后使用 iterator.next() 方法逐步运行函数体内的代码。在每个 yield 处,函数体会暂停执行,并将对应 yield 后的表达式的值作为 value 属性的值返回,done 属性为 false。当所有的 yield 语句执行完成后,next 方法调用将返回 value 属性值为 undefineddone 属性为 true

总结

Generator 方法是一种全新的、强大的异步编程方式,它可以让我们更加清晰、简短地处理异步流程,避免了使用回调函数和 Promise 时可能出现的回调地狱或 Promise 嵌套的情况。使用 Generator 方法也可以让我们更好地理解 JavaScript 运行机制,深入了解 JavaScript 的底层原理。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65ba04aaadd4f0e0ff29073a