学习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 * undefined
, y = 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 * 12
, y = 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的基本认识和使用的主要内容,如果未能解决你的问题,请参考以下文章
ES6 从入门到精通 # 15:生成器 Generator 的用法