ES6:Generator生成器的介绍及场景应用
一、Generator生成器函数
在JavaScript中,一旦一个函数开始执行,就会一次执行到最后或者遇到return时结束,在函数运行期间没有任何代码可以让它在执行过程中暂停。 而Generator生成器函数的出现,使得这样一个不可能成为可能。 Generator函数是ES6提供的一种异步编程解决方案,其形式上与普通函数稍微有些差别:
-
function关键字后跟一个星号(*) yield语句可以暂停函数
function* fn(x) { yield ++x //第一个暂停点 yield ++x //第二个暂停点 yield ++x //第三个暂停点 } let g = fn(0) g.next() // {value: 1, done: false} g.next() // {value: 2, done: false} g.next() // {value: 3, done: false} g.next() // {value: undefined, done: true}
我们通过以上示例可以看到:
-
在fn生成器函数中,通过yield关键字生成了三个暂停点。 而当我们调用fn函数时,会返回一个遍历器对象g,遍历器对象身上有一个next方法,next方法可以恢复执行,而yield表达式是暂停执行的标记。 每次调用next函数会返回一个对象,对象中会有value属性与done属性(value表示本次暂停点表达式的值(yield后面的值),done表示是否遍历完成 )
其实Generator函数会返回一带有Iterator接口的对象,这里主要讨论Generator生成器,有兴趣的话可以看看这篇文章,来了解什么是Iterator接口:https://blog..net/weixin_60297362/article/details/122838780
next方法
一般情况下,next 方法不传入参数的时候,yield 表达式的返回值是 undefined 。当 next 传入参数的时候,该参数会作为上一步yield的返回值。
function* fn(x) { var x = yield ++x //第一个暂停点 console.log(x); var y = yield ++x //第二个暂停点 console.log(y); var z = yield ++x //第三个暂停点 } let g = fn(0) console.log(g.next()) console.log(g.next(1)) console.log(g.next(2))
return方法
return 方法返回给定值,并结束遍历 Generator 函数。 return 方法提供参数时,返回该参数;不提供参数时,返回 undefined 。
function* fn(x) { yield ++x //第一个暂停点 yield ++x //第二个暂停点 yield ++x //第三个暂停点 } let g = fn(0) g.next(0) // {value: 1, done: false} g.return(foo) // {value: foo, done: true} g.next() // {value: undefined, done: true}
二、应用:解决Js异步编程(回调地狱)
要求:1s后打印111,2s后打印222,3s打印333
1.不用generator生成器
setTimeout(() => { console.log(111); setTimeout(() => { console.log(222); setTimeout(() => { console.log(333); }, 3000) }, 2000) }, 1000)
2.用generator生成器
function one() { setTimeout(() => { console.log(111); iterator.next() //执行第二个暂停点 },1000) } function two() { setTimeout(() => { console.log(222); iterator.next() //执行第三个暂停点 },2000) } function three() { setTimeout(() => { console.log(333); },3000) } function * gen() { yield one() yield two() yield three() } let iterator = gen() iterator.next() //执行第一个暂停点
下一篇:
Java面试都只是背答案吗?