Generator 函数是一种特殊的函数,在 ECMAScript 2015 中被引入。这种函数不像普通函数一样运行到底就返回,而是可以暂停执行,并且可以根据需要再次开始执行。在 ECMAScript 2019 中,Generator 函数有了更多的特性和用法,本文将详细介绍如何使用它们。
基本语法和工作原理
定义 Generator 函数的语法非常简单,就是在函数关键字 function
后面加上一个星号。
function* generator() { // some code here }
调用 Generator 函数并不会立即执行函数体内的代码,而是返回一个指向内部状态的迭代器对象,也就是说函数内部的代码只有在迭代器的 next()
方法被调用时才会执行。
const iterator = generator(); const result = iterator.next(); console.log(result); // { value: undefined, done: true }
在第一次调用 next()
方法时,Generator 函数内部的代码会运行到第一个 yield
语句处,然后将 yield
后面的值返回给 next()
方法,并将函数运行状态作为 done
属性一起返回。再次调用 next()
方法时,函数将从上次停下的位置继续执行,直到运行完所有代码或者遇到下一个 yield
语句为止。
-- -------------------- ---- ------- --------- ----------- - --------------------- ----- -- -- - - ----------- ---------------------- ----- -- -- - - ----------- --------------------- ----- -- -- - - ----------- - ----- -------- - ------------ ----------------------------- -- - ------ -- ----- ----- - ----------------------------- -- - ------ -- ----- ----- - ----------------------------- -- - ------ -- ----- ----- - ----------------------------- -- - ------ ---------- ----- ---- -
在最后一次调用 next()
方法时,Generator 函数返回的值是 { value: undefined, done: true }
,也就是说函数已经运行到底部并且没有再返回任何值了。
使用 yield*
在 Generator 函数中,yield
后面可以调用其他的 Generator 函数,这种语法被称作 yield*
。使用 yield*
关键字时,Generator 函数会暂停自己并且执行被调用的 Generator 函数,待调用的函数运行结束后,控制权回到原始的 Generator 函数中,以便将结果值返回给调用者。
-- -------------------- ---- ------- --------- ------------ - ----- ---- ------ ------------- ----- ---- - --------- ------------ - ----- ---- - ----- -------- - ------------- ----------------------------- -- - ------ ---- ----- ----- - ----------------------------- -- - ------ ---- ----- ----- - ----------------------------- -- - ------ ---- ----- ----- - ----------------------------- -- - ------ ---------- ----- ---- -
在这个例子中,当 generator1()
函数执行到 yield* generator2()
的时候,它会暂停执行,然后开始运行 generator2()
函数。当 generator2()
函数执行完毕之后,控制权回到 generator1()
函数中,并且从上次暂停的位置继续运行。
使用参数和返回值
Generator 函数可以接受参数并且返回值,这些特性都很容易使用。
-- -------------------- ---- ------- --------- ---------------- - ----- ------ - ----- ----- - -- ----- ------ - -- - ----- -------- - ------------- ----------------------------- -- - ------ -- ----- ----- - ------------------------------ -- - ------ -- ----- ----- - ----------------------------- -- - ------ ---------- ----- ---- -
在这个例子中,当我们调用 generator(1)
时,我们将 1 作为参数传递给了 Generator 函数。当我们第一次调用 next()
方法时,代码运行到 yield value + 1
处,将 2 作为 value
变量的值返回,此时控制权返回给调用者,我们可以将任何值通过第二次调用 next()
方法的参数传递给 result
变量,在这个例子中我们传递了 2。最后一次调用 next()
方法将代码运行到结尾并且返回 { value: undefined, done: true }
。
实战应用:生成器函数与 Promise
在实际应用中,Generator 函数可以非常方便地与 Promise 结合使用,以实现异步任务的序列化执行。
-- -------------------- ---- ------- -------- -------------- - ------ --- ----------------- ------- -- - ------------- -- - ------------- ---- --------- -- ------ --- - --------- ----------- - ----- ----- - ----- -------------------------------------- ------------------- ----- ----- - ----- -------------------------------------- ------------------- - -------- ----------------------- - ----- -------- - ------------ -------- -------------------- - -- ------------- - ------ ------------------------------ - ------ ------------------------ -- - ------ ---------------------------------- ---------------- -- - ------ ---------------------- --- - ------ ------------------------------ - ------------------------------------- -- - -------------------- ---------------- -- - --------------------- ---
在这个例子中,我们定义了一个 fetchData()
函数,它返回一个 Promise 对象,在一秒钟后解析为一个字符串。然后我们定义了一个 generator()
函数,它使用 yield
语句依次调用两次 fetchData()
函数,并且在每次调用时打印返回的数据。最后我们定义了一个 runGenerator()
函数,它将执行 generator()
函数,然后在每次执行 fetchData()
函数时使用 Promise 对象传递数据和控制权,以便实现异步任务的序列化执行。
总结
Generator 函数是一种强大的函数,可以让我们使用类似于普通的同步代码的方式编写异步任务。本文介绍了 Generator 函数的基本语法和工作原理,以及如何使用 yield*
、参数和返回值。最后我们还通过一个实际应用案例展示了如何将 Generator 函数与 Promise 结合使用。如果你想进一步学习 Generator 函数的使用,可以参考 MDN 的文档。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64852ade48841e9894414eb8