Generator函数的中断与恢复
Generator是JS中一种特殊的函数,它能通过迭代器协议(Iterator Protocol)实现中断与恢复功能。
Generator函数使用function*
声明,调用Generator函数时不会立即执行,而是返回一个迭代器对象。通过调用迭代器的next()
方法,可以逐步执行Generator函数。Generator函数内部可以使用yield
关键字定义中断点。当调用next()
时,会从上次暂停的地方继续执行,直到遇到下一个yield
关键字或函数结束。通过不断调用next()
方法,可以逐步执行Generator函数,并获取每个中断点处的值。
function* generatorFunction() { console.log("1"); yield; console.log("2"); yield; console.log("3");}const generator = generatorFunction();generator.next(); // 1generator.next(); // 2generator.next(); // 3
由于Generator函数具有中断和恢复的特性,可以用于异步编程。通过yield
关键字,将异步操作分割成多个步骤,每个步骤都可以通过yield
暂停,等待异步操作完成后再恢复执行。
获取中断点处的值
function* generatorFunction() { yield "hello"; yield "world"; yield "ending";}const generator = generatorFunction();const a = generator.next(); // { value: "hello", done: false }const b = generator.next(); // { value: "world", done: false }const c = generator.next(); // { value: "ending", done: true }const d = generator.next(); // { value: undefined, done: true }
yield*
yield*
用来在一个Generator函数里执行另一个Generator函数。
function* foo() { yield "aaa"; yield "bbb";}function* bar() { yield * foo(); yield "ccc"; yield "ddd";}const generator = bar();const a = generator.next(); // { value: "aaa", done: false }const b = generator.next(); // { value: "bbb", done: false }const c = generator.next(); // { value: "ccc", done: false }const d = generator.next(); // { value: "ddd", done: false }const e = generator.next(); // { value: undefined, done: true }
bar
里面,执行到e
这一步done
才变成true
是因为,bar
实际上相当于是
function* bar() { yield * foo(); yield "ccc"; yield "ddd"; return undefined;}
所以遇到return
才done。
next()
的参数
yield
表达式本身没有返回值。比如
const result = yield 3 + 4 + 5;
当执行到yield 3 + 4 + 5
的时候会暂停;当执行next()
方法后,此时执行const result = [yield 3 + 4 + 5]
,这个时候result
的值是undefined
。
但是next()
可以传一个参数,这个参数会被当作yield
的返回值。因此如果执行next(10)
,此时result
的值则为10
。即const result = next(10)
。
for...of
迭代器对象(Iterator)可以使用for...of
遍历。这里需要注意,一旦next()
方法的返回对象的done
属性为true
,for...of
循环就会终止,且不包含该返回对象。
function* generatorFunction() { yield 1; yield 2; yield 3; yield 4; return 5;}for (const item of generatorFunction()) { console.log(item);}// 1// 2// 3// 4
Generator.prototype.return
return
方法可以提前终结遍历器函数
function* generatorFunction() { yield 1; yield 2; yield 3;}const generator = generatorFunction();generator.next(); // { value: 1, done: false }generator.return("end"); // { value: "end", done: true }generator.next(); // { value: undefined, done: true }