ES6|学习ES6系列(generator的基本认识和使用)

每天对自己多问几个为什么,总是有着想象不到的收获。 一个菜鸟小白的成长之路(copyer)

前言 ? 今天是国庆节的第二天,回到家中,还是比较的无聊,还是写写代码吧。毕竟是个代码小白,需要学习的东西还是很多的,加油吧!
? 最近在学习redux-saga这个中间件,它其中的内部代码的原理就是 ES6中的 generator,但是呢?我对其中的ES6的generator就有点陌生,还是不是很理解,所以还是先学习基本的语法吧。
? 其中的很多话,就是摘抄与阮一峰的ES6的讲解(都标识了引用的)

基本认识
Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。
简单理解:
Generator 函数是一个状态机,封装了多个内部状态。
执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态

generator函数的基本定义
function * foo(x, y) { ··· } function *foo(x, y) { ··· } function* foo(x, y) { ··· } function*foo(x, y) { ··· }

但是呢,比较的推荐第三种,因为在vscode 的一些插件中,格式化的时候,就是格式化成第三种。

基本实例
function * foo() {yield 'james' yield 'kobe' } let it = foo() console.log(it);

  • 调用函数,跟普通的函数一样 foo()
  • 返回对象:一个指向内部状态的指针对象 遍历器对象(Iterator Object)
拿取函数内部的状态,就必须要调用遍历器对象的next()方法
必须调用遍历器对象的next方法,使得指针移向下一个状态。也就是说,每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。
it.next() // { value: 'james', done: false }it.next() // { value: 'kobe', done: false }it.next() // { value: undefined, done: true }

从上面可以看出
从上面的代码中,可以看出,上面的generator函数是有三种状态的,所以需要调用三次的next(),

generator函数的执行顺序
ES6|学习ES6系列(generator的基本认识和使用)
文章图片

如果想要最后一次有值,不为undefined,就return一个值出来。

next的参数
  • yield表达式本身没有返回值,或者说总是返回undefined
  • next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。
没有参数的情况
function* foo(x) {var y = 2 * (yield (x + 1)); var z = yield (y / 3); return (x + y + z); }let a = foo(5); a.next() // Object{value:6, done:false} a.next() // Object{value:NaN, done:false} a.next() // Object{value:NaN, done:true}

第一次 next : value为6
第二次next: yield的返回值值undefined,y = 2 * undefinedy = NaN, value为 undefined
第三次next: y, z都是undefined, value 为 undefined

有参数的情况
let b = foo(5); b.next() // { value:6, done:false } b.next(12) // { value:8, done:false } b.next(13) // { value:42, done:true }

第一次 next : value为6
第二次next: ,y = 2 * 12y = 24, value为 8
第三次next: yield的返回值值13, y = 24, z = 13, x = 5, value 为 42

generator函数和promise的结合使用
function* foo() {const result = yield new Promise((resolve, reject) => {setTimeout(() => {resolve('hello world') }, 3000) }) console.log(result); }const it = foo() it.next().value.then(res => {it.next(res) })

【ES6|学习ES6系列(generator的基本认识和使用)】现象: 异步代码实现同步 ,也就是result的代码是同步的
代码解析
// 返回一个遍历器对象 it.next()// 拿到promise对象 it.next().value// 拿到异步的 resolve的结果 res it.next().value.then(res => { ... })// 把 res传递给第二次next,return出去 it.next().value.then(res => {it.next(rex) })这样res就是最新的代码


结语 generator的基本用法大致就是这样了,看看还是比较好理解的。
学习使我快乐。

    推荐阅读