We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
generator在《ECMAScript 6 入门》中的定义:
Generator 函数是一个状态机,封装了多个内部状态。执行 Generator 函数会返回一个遍历器对象(Iterator),也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。
简单看看它的使用:
function* gen(n) { const x = yield n + 5 const y = yield x + 5 return y } const it = gen(5) it.next() // { value: 10, done: false } it.next(10) // { value: 15, done: false } it.next(20) // { value: 20, done: true } it.next() // { value: undefined, done: true }
值得注意的几个地方:
generator
next
yield
value
return
当然,在我们平时使用中,yield后面一般会是Promise
Promise
generator函数对我们来说其实并不陌生,async作为generator的语法糖,使用async其实间接的使用了generator,实现generator的自动执行,就是为了帮我们更好的了解async函数的工作方式。在async之前,就已经出现了类似的解决方案,如co模块,它能够实现generator的自动执行,后来将它纳入了标准中,所以,我们要实现的,其实就是co模块。
async
co
关于generator的更多细节可以参考阮一峰老师的《ECMAScript 6 入门》
我们的目的在于了解generator函数自动执行的核心逻辑,所以,要实现的是理想状态下的co模块myco,它接收generator函数作为参数
myco
const promise = function(v) { return new Promise(resolve => { setTimeout(() => { resolve(v) }, 1000) }) } const gen = function* () { const res1 = yield promise(5) console.log(res1) const res2 = yield promise(res1 + 5) console.log(res2) return (res1 + res2) } myco(gen)
第一版:
function myco(gen) { const it = gen() const { value, done } = it.next() value.then(res => { const { value, done } = it.next(res) value.then(res => { const { value, done } = it.next(res) if (done) { // 结束 } }) }) } myco(gen) // 1s后 5 // 2s后 10
以上代码中,第一次调用next(),函数gen开始执行,遇到yield暂停执行并返回它后面的promise,该promise在resolve的时候再次调用next(),函数gen恢复执行,遇到第二个yield再次暂停并返回后面的值,如此往复,直到gen函数执行完毕。理解这个过程,我们可以将myco改成递归的方式
next()
gen
promise
resolve
注意:next()的参数会成为上一个yield的返回值,这样的好处在于我们可以不停向函数gen中注入值,这种机制使我们可以以同步的方式来表达异步操作,这样更易于理解
第二版:
function myco(gen) { const it = gen() function step(v) { const { value, done } = it.next(v) if (done) return value.then(res => { step(res) }) } step() }
最后,myco函数会返回一个Promise,该Promise的状态会在gen函数执行完毕的时候resolve
最终版:
function myco(gen) { return new Promise(resolve => { const it = gen() function step(v) { const { value, done } = it.next(v) if (done) return resolve(value) value.then(res => { step(res) }) } step() }) } myco(gen).then(res => { console.log(res) }) // 1s后 5 // 2s后 10 15
The text was updated successfully, but these errors were encountered:
No branches or pull requests
关于generator函数
generator在《ECMAScript 6 入门》中的定义:
简单看看它的使用:
值得注意的几个地方:
generator
函数并不会执行其中的代码,而是返回一个遍历器对象next
方法generator函数才开始执行,并停在第一个yield
的地方,再次调用next
,函数恢复执行,停在下一个yield
,如此直到函数执行完毕next
方法的返回值是一个对象,该对象value
属性是yield
后面的内容next
方法的参数,是上下一个yield
的返回值,这使得我们可以不停向generator
函数中传递数据yield
,但只能有一个return
当然,在我们平时使用中,
yield
后面一般会是Promise
generator
函数对我们来说其实并不陌生,async
作为generator
的语法糖,使用async
其实间接的使用了generator
,实现generator
的自动执行,就是为了帮我们更好的了解async
函数的工作方式。在async
之前,就已经出现了类似的解决方案,如co
模块,它能够实现generator
的自动执行,后来将它纳入了标准中,所以,我们要实现的,其实就是co
模块。关于
generator
的更多细节可以参考阮一峰老师的《ECMAScript 6 入门》实现
我们的目的在于了解
generator
函数自动执行的核心逻辑,所以,要实现的是理想状态下的co
模块myco
,它接收generator
函数作为参数第一版:
以上代码中,第一次调用
next()
,函数gen
开始执行,遇到yield
暂停执行并返回它后面的promise
,该promise
在resolve
的时候再次调用next()
,函数gen恢复执行,遇到第二个yield
再次暂停并返回后面的值,如此往复,直到gen
函数执行完毕。理解这个过程,我们可以将myco
改成递归的方式注意:
next()
的参数会成为上一个yield
的返回值,这样的好处在于我们可以不停向函数gen
中注入值,这种机制使我们可以以同步的方式来表达异步操作,这样更易于理解第二版:
最后,
myco
函数会返回一个Promise
,该Promise
的状态会在gen
函数执行完毕的时候resolve
最终版:
The text was updated successfully, but these errors were encountered: