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.csdn.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() //执行第一个暂停点

猜你喜欢

转载自blog.csdn.net/weixin_60297362/article/details/123282959
今日推荐