📜  javascript中的生成器(1)

📅  最后修改于: 2023-12-03 15:01:48.172000             🧑  作者: Mango

JavaScript 中的生成器

在 JavaScript 中,生成器是一个特殊的函数,它能够暂停执行,保存状态,并在需要时继续执行。我们可以使用生成器来结束回调地狱,使代码更加简洁和易于理解。

基本语法

生成器函数需要使用 function* 关键字来声明,且函数体中必须包含关键字 yield。示例如下:

function* generator() {
  yield 'hello';
  yield 'world';
  yield '!';
}

const gen = generator();
console.log(gen.next()); // {value: 'hello', done: false}
console.log(gen.next()); // {value: 'world', done: false}
console.log(gen.next()); // {value: '!', done: false}
console.log(gen.next()); // {value: undefined, done: true}

在上述示例中,我们定义了一个生成器函数 generator,并通过调用该函数创建了一个生成器对象 gen。通过调用生成器对象的 next 方法,我们可以逐一获取每一次 yield 表达式的值。

yield 表达式

yield 表达式可以看作是生成器函数的暂停标志,它将表示函数执行状态的对象返回给调用者,并暂停函数的执行。每次调用生成器对象的 next 方法时,函数将从上一次暂停的位置恢复执行,并修改表示函数执行状态的对象的 value 属性。

function* add(a, b) {
  yield a + b;  // 3
  const c = yield;  // yield 的 return value 为 undefined
  yield a + b + c;
}

const gen = add(1, 2);
console.log(gen.next()); // {value: 3, done: false}
console.log(gen.next()); // {value: undefined, done: false}
console.log(gen.next(4)); // {value: 7, done: false}
console.log(gen.next()); // {value: undefined, done: true}

在上述示例中,我们定义了一个生成器函数 add,并通过调用该函数创建了一个生成器对象 gen。在第一次调用 gen.next() 时,yield a + b; 的值为 3,表示执行到了该语句。在第二次调用 gen.next() 时,函数执行到了 const c = yield,并等待外部传入一个参数。在第三次调用 gen.next(4) 时,yield a + b + c 的值为 7,表示执行到了该语句。

从第二次调用 gen.next() 开始,我们没有传入参数,此时 yield 表达式的返回值将为 undefined

生成器实现异步

生成器可以实现异步的效果,代码更加清晰易读。下面的示例展示了如何使用生成器实现异步逻辑:

function asyncFunc() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('hello world');
    }, 2000);
  });
}

function* asyncGenerator() {
  const result = yield asyncFunc();
  console.log(result);
}

const gen = asyncGenerator();
const promise = gen.next().value;
promise.then(res => gen.next(res));

在上述示例中,我们通过定义一个异步函数 asyncFunc,在生成器函数的语句中使用 yield asyncFunc(),并将其返回值赋值给变量 result。我们通过返回 Promise 对象的方式来实现异步,最后在调用 promise.then 时,将异步执行结果传回给生成器对象。当异步函数执行完成后,console.log(result) 将在控制台中打印出 'hello world'。

注意事项

在使用生成器函数时需要注意以下几点:

  • 在执行生成器函数时,函数不会立即执行,而是返回一个生成器对象。
  • 生成器对象的 next 方法不需要传入参数,但如果传入参数,则表示上一次 yield 表达式的返回值。
  • 在生成器函数中,只能使用 yield 表达式暂停函数执行,任何其它语句都会导致语法错误。
  • 在使用生成器函数时,需要注意保持异步执行的顺序,以防止逻辑错误的发生。
结语

通过本文,我们了解了 JavaScript 中的生成器函数及其基本语法、应用场景和注意事项。使用生成器函数可以优雅地解决异步回调地狱和可读性问题,但需要遵循其使用规范。