共计 3742 个字符,预计需要花费 10 分钟才能阅读完成。
“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()
办法返回一个蕴含属性done
和value
的对象。该办法也能够通过承受一个参数用以向生成器传值
返回的对象蕴含两个属性:
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()
办法用来向生成器抛出异样,并复原生成器的执行,返回带有done
及value
两个属性的对象
done
(布尔类型)- 如果迭代器曾经返回了迭代序列的开端,则值为
true
。在这种状况下,能够指定迭代器value
的返回值。 - 如果迭代可能持续生产在序列中的下一个值,则值为
false
。这相当于不指定done
属性的值。 value
– 迭代器返回的任何JavaScript
值。当done
是true
的时候能够省略。
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
and10, 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
anda
- B:
a
andundefined
- C:
['a', 'b', 'c']
anda
- 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*2
。i
等于 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()
则会继续返回 b
和c
直到该数组调用完结。。
console.log(two.next().value) // 'a'
console.log(two.next().value) // 'b'
console.log(two.next().value) // 'c'
console.log(two.next().value) // undefined