【javascript】generator函数

JavaScript 中的 Generator 函数 是一种特殊的函数类型,它能够中断并恢复执行,这使得它在处理复杂的异步逻辑、协程等场景中非常有用。它的行为与普通的函数不同,因为它可以在执行过程中暂停,允许函数在某个点上"暂停"执行,之后可以继续从暂停点执行。 @TOC

什么是 Generator 函数?

Generator 函数通过 function* 声明,返回一个特殊的 Generator 对象 ,其核心机制是 yield 关键字。这个对象有一个可以"暂停"并在以后恢复执行的能力。

当调用一个 Generator 函数时,它不会立即执行,而是返回一个 Generator 对象。

调用next()函数在每个 yield 语句处暂停。当我们调用 next() 时,它会继续执行到下一个 yield

例子:

javascript 复制代码
function* count() {
  console.log("Start");
  yield 1;
  console.log("Continue");
  yield 2;
  console.log("End");
  yield 3;
}

const counter = count();// 返回 Generator 对象
console.log(counter.next()); // Start 1
console.log(counter.next()); // Continue 2
console.log(counter.next()); // End 3

1.next() 方法

作用

  • next() 是控制 Generator 执行的主要方法,它会恢复 Generator 函数的执行,直到下一个 yield。
  • 每次调用 next(),都会返回一个对象 { value, done }:
    • value: 当前 yield 表达式的返回值。
    • done: 布尔值,指示生成器是否已完成执行。

用法与返回值

js 复制代码
function* gen() {
  yield 1;
  yield 2;
  return 3;
}

const g = gen();
console.log(g.next()); // { value: 1, done: false }
console.log(g.next()); // { value: 2, done: false }
console.log(g.next()); // { value: 3, done: true }
console.log(g.next()); // { value: undefined, done: true }
  • g.next() :调用 next() 时,Generator 会继续执行,直到遇到下一个 yield 或函数结束。如果没有 yield,它会直接返回一个 done: true 对象。

参数传递

next() 可以接收一个参数,这个参数会作为上一次 yield 表达式的返回值,传递给生成器。

javascript 复制代码
function* gen() {
  const a = yield 'What is your name?';
  const b = yield 'What is your age?';
  return `${a} is ${b} years old.`;
}

const g = gen();
console.log(g.next());            // { value: 'What is your name?', done: false }
console.log(g.next('Alice'));     // { value: 'What is your age?', done: false }
console.log(g.next(30));          // { value: 'Alice is 30 years old.', done: true }

在上述代码中,第一次 next() 返回一个字符串 'What is your name?'。当我们向生成器传递参数('Alice' 和 30)时,参数会依次传递给 a 和 b,最终返回 "Alice is 30 years old."。

3. throw() 方法

作用

  • throw() 方法可以用来在 Generator 函数中抛出错误。
  • 它会中断当前的 yield 并跳到最近的 catch 块中。如果 Generator 中没有 try-catch 语句捕获错误,那么 throw() 会终止执行,并返回一个 done: true 的结果。

用法与返回值

javascript 复制代码
function* gen() {
  try {
    yield 1;
  } catch (err) {
    console.log(err); // 捕获到错误
    yield 2;
  }
  yield 3;
}

const g = gen();
console.log(g.next()); // { value: 1, done: false }
console.log(g.throw("Oops!")); // "Oops!" { value: 2, done: false }
console.log(g.next()); // { value: 3, done: true }
  • g.throw("Oops!") :在执行到 yield 1 时,抛出一个错误 Oops!,这个错误会被 try-catch 捕获,并在捕获后继续执行 yield 2。如果 throw() 被调用的时机不合适(比如没有 try-catch),生成器将停止执行并返回一个 { value: undefined, done: true } 对象。

没有 catch 时的行为

javascript 复制代码
function* gen() {
  yield 1;
  yield 2;
}

const g = gen();
console.log(g.next()); // { value: 1, done: false }
console.log(g.throw("Error")); // Error { value: undefined, done: true }

在这个例子中,调用 g.throw() 会导致生成器抛出错误并终止执行,因为没有 catch 语句来捕获该错误。

4. return() 方法

作用

  • return() 用于提前结束 Generator 函数,并返回一个结果。
  • return() 会使得生成器结束执行,并返回 { value, done: true } 对象,done 属性为 true。
  • 返回的 value 会作为返回值传递给 return() 调用的地方。

用法与返回值

javascript 复制代码
function* gen() {
  yield 1;
  yield 2;
  return 3;
}

const g = gen();
console.log(g.next()); // { value: 1, done: false }
console.log(g.return(4)); // { value: 4, done: true }
console.log(g.next()); // { value: undefined, done: true }
  • g.return(4) :这个方法会立即结束生成器,并返回 { value: 4, done: true }。注意:如果在 Generator 函数中调用 return,它会停止 Generator 的执行。

5. next(), throw(), return() 的总结与对比

方法 作用 返回值 适用场景
next() 恢复执行 Generator,直到下一个 yield 或结束 { value: any, done: boolean } 用于继续执行 Generator,并返回下一个 yield 的值。
throw() 在 Generator 中抛出一个错误 { value: any, done: boolean } 用于处理错误,并在 Generator 内部抛出异常。
return() 结束 Generator 函数的执行 { value: any, done: true } 用于提前结束 Generator,并返回结果。

总结

Generator 函数和其方法(next(), throw(), return())提供了对函数执行流程的精确控制。通过 yield 暂停执行,next() 恢复执行,throw() 处理错误,return() 提前结束生成器,这使得 Generator 函数在处理异步编程、协程、流控制等场景中非常有用。掌握这些方法,可以帮助开发者更好地控制异步操作和复杂逻辑的执行过程。

相关推荐
螺丝钉tina11 小时前
[Playwright] [02]常用命令与调试:Debug UI、Mode和 Trace Viewer
开发语言·javascript·测试工具·ui·自动化
开开心心就好12 小时前
竖式除法出题工具,整除余数混合模式
运维·服务器·前端·javascript·ocr·perl·1024程序员节
এ慕ོ冬℘゜12 小时前
JS 事件循环、宏任务微任务:单线程底层原理 + 执行顺序
开发语言·javascript·ecmascript
web打印社区13 小时前
Lodop排障总纲-常见报错一张表
开发语言·前端·javascript·chrome·websocket
程序员大阳13 小时前
副队长JavaScript教程(56)-DOM之表单操作
javascript·dom·表单操作
Dxy123931021614 小时前
JS AES加密详解
开发语言·javascript·ecmascript
FRing0314 小时前
JavaScript入门到精通三十三(异常处理、call方法、apply方法、bind方法、防抖、节流)
开发语言·前端·javascript
jktantan15 小时前
(二)Vue 3 的 attrs 不是响应式:el-form 扩展属性同步的三种方案
前端·javascript·vue.js·element-plus
echome88816 小时前
JavaScript async/await 错误处理:别让 Promise 静默失败
开发语言·前端·javascript·promise
#麻辣小龙虾#17 小时前
网页布局css中flex+margin的组合布局技巧
开发语言·前端·javascript