学习ES6系列:generator的基本认识和使用

Posted copyer_xyf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习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函数的执行顺序

如果想要最后一次有值,不为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)
})

现象: 异步代码实现同步 ,也就是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的基本用法大致就是这样了,看看还是比较好理解的。

学习使我快乐。

以上是关于学习ES6系列:generator的基本认识和使用的主要内容,如果未能解决你的问题,请参考以下文章

js es6深入应用系列(Generator)

js es6深入应用系列(Generator)

ES6 从入门到精通 # 15:生成器 Generator 的用法

ES6 从入门到精通 # 15:生成器 Generator 的用法

ES6,ES7,Vue的基本认识和特点

ES6 从入门到精通 # 16:Generator 的应用