JavaScript异步之generator函数

版权声明:刘家军 https://blog.csdn.net/qq_42911663/article/details/86064759

接触过Ajax请求的会遇到过异步调用的问题,为了保证调用顺序的正确性,一般我们会在回调函数中调用,也有用到一些新的解决方案如Promise相关的技术。

在异步编程中,还有一种常用的解决方案,它就是Generator生成器函数。顾名思义,它是一个生成器,它也是一个状态机,内部拥有值及相关的状态,生成器返回一个迭代器Iterator对象,我们可以通过这个迭代器,手动地遍历相关的值、状态,保证正确的执行顺序。

generator基本用法

最简单的generator函数,其实它就是一个普通的函数,但是它有两个特征:
1.就是function关键字与函数名之间有一个*号,
2.就是函数体内使用yield表达式来遍历状态:

function* generator(){
yield 'one'
yield 'two'
return 'three'
}
let Ljj = generator()
console.log(Ljj)
console.log(Ljj.next())  
console.log(Ljj.next())
console.log(Ljj.next())
console.log(Ljj.next())

输出:
在这里插入图片描述
定义了一个generator的生成器函数,调用之后返回了一个迭代器对象Ljj

调用next方法后,函数内执行第一条yield语句,输出当前的状态done(生成器函数是否已经执行完毕并返回)以及返回值value(一般为yield关键字后面的运算结果)

每调用一次next,则执行一次yield语句,并在该处暂停

当在生成器函数中显式 return 时,会导致生成器立即变为完成状态,就退出了生成器函数,后续如果还有yield操作就不再执行了,即调用 next() 方法返回的对象的 done 为 true。如果 return 后面跟了一个值,那么这个值会作为当前调用 next() 方法返回的 value 值。

yield和yield*

function* generator() {
      yield 'one'
      yield* generator2(13)
      return 'three'
}
function* generator2(num) {
      yield num
      yield num + 1
}
let Ljj = generator()
console.log(Ljj.next())
console.log(Ljj.next())
console.log(Ljj.next())
console.log(Ljj.next())

输出:
在这里插入图片描述
从上面例子上我们可以看出:
当这个迭代器的 next() 方法被调用时,其内的语句会执行到第一个(后续)出现yield的位置为止,yield 是你给什么它提取什么,但是 yield* 会继续向下请求,将执行权移交给另一个生成器函数(generator2),当前生成器(generator)暂停执行,直到没的提取为止。
注意yieldyield* 只能在generator函数内部使用,一般的函数内使用会报错

next()中的传参

调用 next()方法时,如果传入了参数,那么这个参数会作为上一条执行的 yield 语句的返回值,例如:

function* generator(){
    x = yield 1;
    y = yield x * 2;
    yield y * 3;
}

var Ljj = generator();
console.log(Ljj.next());
console.log(Ljj.next());
console.log(Ljj.next(2));
console.log(Ljj.next());

输出:
在这里插入图片描述
第一次调用next之后返回值x为1,但在第二次调用next的时候x其实是undefined的,因为generator不会自动保存相应变量值,我们需要手动的指定,这时y值为NaN,在第三次调用next的时候执行到yield 3 * y,通过传参将上次yield返回值y设为2,得到结果6

for…of循环代替next()

除了使用.next()方法遍历迭代器对象外,通过ES6提供的新循环方式for…of也可遍历,但与next不同的是,它会忽略return返回的值:

function* generator() {
    yield 1;
    yield 2;
    return 3;
}

var Ljj = generator();

for (let i of Ljj ) {
    console.log(i) // 1 2
}

更多参考 参考 MDN - Generator
明日我们开始讲一下JavaScript异步之async

友情链接:点击查看所有文章目录

友情链接:点击查看 JavaScript异步系列文章目录

猜你喜欢

转载自blog.csdn.net/qq_42911663/article/details/86064759