"Code tailor",为前端开发者提供技术相干资讯以及系列根底文章,微信关注“小和山的菜鸟们”公众号,及时获取最新文章。

前言

在开始学习之前,咱们想要告诉您的是,本文章是对阮一峰《ECMAScript6 入门》一书中 "Generator" 章节的总结,如果您已把握上面常识事项,则可跳过此环节间接进入题目练习

  • 什么是 Generator?
  • 如何创立和应用?
  • 如何在异步中利用?
  • 优缺点

如果您对某些局部有些忘记, 曾经为您筹备好了!

学习链接

Generator 的学习

Generator 的异步利用

汇总总结

概念

Generator函数是 ES6 中提供的一种异步编程解决方案。语法上,首先能够把它了解成,Generator 函数是一个状态机,封装了多个外部状态,须要应用next()函数来继续执行上面的代码。

创立和应用

function* helloWorldGenerator() {  yield 'hello'  yield 'world'  return 'ending'}var hw = helloWorldGenerator()hw.next()// { value: 'hello', done: false }hw.next()// { value: 'world', done: false }hw.next()// { value: 'ending', done: true }hw.next()// { value: undefined, done: true }

罕用办法

  • Generator.prototype.next()
next() 办法返回一个蕴含属性 donevalue 的对象。该办法也能够通过承受一个参数用以向生成器传值

返回的对象蕴含两个属性:

  • done (布尔类型)
  • 如果迭代器超过迭代序列的开端,则值为 true。 在这种状况下,value 可选地指定迭代器的返回值。
  • 如果迭代器可能生成序列中的下一个值,则值为 false。 这相当于没有齐全指定 done 属性。
  • value - 迭代器返回的任意的 Javascript 值。当 done 的值为 true 时能够疏忽该值。
function* gen() {  yield 1  yield 2  yield 3}var g = gen() // "Generator { }"g.next() // "Object { value: 1, done: false }"g.next() // "Object { value: 2, done: false }"g.next() // "Object { value: 3, done: false }"g.next() // "Object { value: undefined, done: true }"
  • Generator.prototype.return()
return() 办法返回给定的值并完结生成器
function* gen() {  yield 1  yield 2  yield 3}var g = gen()g.next() // { value: 1, done: false }g.return('foo') // { value: "foo", done: true }g.next() // { value: undefined, done: true }
  • Generator.prototype.throw()
throw() 办法用来向生成器抛出异样,并复原生成器的执行,返回带有 donevalue 两个属性的对象
  • done (布尔类型)
  • 如果迭代器曾经返回了迭代序列的开端,则值为 true。在这种状况下,能够指定迭代器 value 的返回值。
  • 如果迭代可能持续生产在序列中的下一个值,则值为 false。 这相当于不指定 done 属性的值。
  • value - 迭代器返回的任何 JavaScript 值。当 donetrue 的时候能够省略。
function* gen() {  while (true) {    try {      yield 42    } catch (e) {      console.log('Error caught!')    }  }}var g = gen()g.next() // { value: 42, done: false }g.throw(new Error('Something went wrong')) // "Error caught!"

在异步中的利用

var readFile = function (name, ms) {  return new Promise((resolve, reject) => {    setTimeout(() => {      console.log(name + '读完了')      resolve()    }, ms)  })}var gen = function* () {  console.log('指定generator')  yield readFile('first', 1000)  yield readFile('second', 2000)  return '实现了'}var g = gen()var result = g.next()result.value  .then(() => {    g.next()  })  .then(() => {    g.next()  })

优缺点

长处:

  • 能够管制函数的执行,能够配合 co 函数库应用

毛病:

  • 流程治理却不不便(即何时执行第一阶段、何时执行第二阶段)

更多常识请点击JavaScript 异步发展史

题目自测

一:Generator 函数的 yield 关键字的作用是()?

  • A: 进行执行
  • B: 退出函数
  • C: 暂停执行,期待 next()办法调用
  • D: 进行执行,可自行复原执行

二:如下代码执行后打印后果为()

function* generator(i) {  yield i  yield i * 2}const gen = generator(10)console.log(gen.next().value)console.log(gen.next().value)
  • A: [0, 10], [10, 20]
  • B: 20, 20
  • C: 10, 20
  • D: 0, 10 and 10, 20

三:如下代码执行后打印后果为()

function* generatorOne() {  yield ['a', 'b', 'c']}function* generatorTwo() {  yield* ['a', 'b', 'c']}const one = generatorOne()const two = generatorTwo()console.log(one.next().value)console.log(two.next().value)
  • A: a and a
  • B: a and undefined
  • C: ['a', 'b', 'c'] and a
  • D: a and ['a', 'b', 'c']

题目解析

一、

Answer:C

Generator 函数的调用办法与一般函数一样,也是在函数名前面加上一对圆括号。不同的是,调用 Generator 函数后,该函数并不执行,返回的也不是函数运行后果,而是一个指向外部状态的指针对象,也就是上一章介绍的遍历器对象(Iterator Object)。

下一步,必须调用遍历器对象的 next 办法,使得指针移向下一个状态。也就是说,每次调用 next 办法,外部指针就从函数头部或上一次停下来的中央开始执行,直到遇到下一个 yield 表达式(或 return 语句)为止。换言之,Generator 函数是分段执行的,yield 表达式是暂停执行的标记,而 next 办法能够复原执行。


二、

Answer:C

惯例函数不能在调用后中途进行。然而,生成器函数能够中途“进行”,而后从进行的中央持续。每次生成器函数遇到yield关键字时,该函数都会生成它前面指定的值。留神,在这种状况下,生成器函数不返回值,而是生成值。

首先,咱们初始化生成函数,使 i 等于 10。咱们应用next()办法调用生成器函数。第一次调用生成器函数时,i 等于 10。它遇到第一个 yield 关键字:它产生 i 的值。生成器当初是“暂停”的,10 被记录。

而后,咱们应用next()办法再次调用该函数。它开始在之前进行的中央持续,依然是 i 等于 10。当初,它遇到下一个yield关键字,并产生 i*2i 等于 10,所以它返回 10*2,也就是 20。后果是 10,20


三、

Answer:C

应用yield关键字,咱们在生成器函数中产生值。 应用yield *关键字,咱们能够从另一个生成器函数或可迭代对象(例如,数组)中产生值。 在generatorOne中,咱们应用 yield 关键字产生整个数组['a','b','c']。 一个对象的下一个办法(one.next()。value)返回的对象的 value 属性值等于整个数组['a','b','c']

console.log(one.next().value) // ['a', 'b', 'c']console.log(one.next().value) // undefined

generatorTwo中,咱们应用yield *关键字。 这意味着咱们失去的迭代器为数组['a','b','c']。 第一个产生的值为数组中的第一个值 a,因而咱们第一次调用two.next().value时,将返回 a。前面持续调用next()则会继续返回bc直到该数组调用完结。。

console.log(two.next().value) // 'a'console.log(two.next().value) // 'b'console.log(two.next().value) // 'c'console.log(two.next().value) // undefined