js中generator详解

什么是 Generator

Generator 是 ES6 提供的一种异步编程解决方案。可以把它理解为一种状态管理器。
调用 Generator 函数之后,它只是进行实例化工作,并没有真实的执行内部代码,所以不会像其他函数一样返回函数结果,而是会返回一个指向内部状态的指针对象,也就是所说的迭代器对象,需要继续调用 next 方法,next 方法会返回一个 iterate,以确保后续代码执行。
Generator 特性:

  1. function 关键字与函数名之间需要有一个星号 *;
  2. 调用后不会立即执行函数结果,而是返回一个遍历器对象 iterator ;
  3. Generator 内部需要使用 yield 来定义暂停状态;

next

但是 next 方法遇到 yield 就会停止, 一个 next 只能执行一个 yield 之前的内容,直到下一个 yield 为止。如下:

function* gen() {
	console.log('我在gen函数内部', 1)
    return 1
}
const iterator = gen() //不执行
console.log(iterator.next()) // 执行, 打印{value:1,done:true}

yield

什么是 yield 呢?可以理解为暂停,简单来说 yield + next ~= return ,但是与return 不一样的是, return 是停止执行后面的方法,而 yield 只是停止当前的 next,直到下一个 next 调用的时候,继续执行。如下:

  <script>
    function* gen() {
      yield '我是第一个返回值'
      yield '我是第二个返回值'
      yield '我是第三个返回值'
    }
    let res = gen()
    console.log(res.next()); //value: 我是第一个返回值
    console.log(res.next()); //value: 我是第二个返回值
   	console.log(res.next()); //value: 我是第三个返回
console.log(res.next()); //value: undefined, done: true
  </script

如果 yield 放在了等号的右边,同样也会停止执行后续代码,不会执行等于操作,因为在执行等号之前就已经停止,所以返回值依旧是通过next取到,直到下一个next出现,才会继续之前的操作,如下:

function* gen(num) {
    let r1 = yield 1
    console.log('r1', r1);

    let r2 = yield 2
    console.log('r2', r2);

    let r3 = yield 3
    console.log('r3', r3);

}
const iterator = gen()
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next()) 

async await

其实之所以我们说 Generator 能够把异步变同步,是因为 Generator 函数中我们只需要写同步代码就可以,真正执行异步操作的是迭代器对象。在复杂的业务逻辑中,大量使用迭代器对象来执行异步操作,会使得代码变得很不优雅,于是 ES7 中就推出了 async await 方案来实现异步变同步。 async await 可以理解为一个自执行 Generator 函数,真正的异步操作被封装在底层,这样的写法,使得代码变优雅了很多。如下:

function requestFn () {
	return new Promise ((resolve)=>{
		setTimeout(()=>{
			resolve(1)
		}, 500)
	}
}
functio async gen(num) {
    console.log('r1')
    let r1 = await requestFn()
    console.log('r2')
	return r1
}

gen().then(res=>{
	console.log('r3', res)
}
// r1  500ms  r2  r3 1

你可能感兴趣的:(javascript,前端,开发语言)