生成器函数
使用方法
- 调用生成器函数不会去执行函数,而是会得到一个生成器对象;
- 调用生成器对象的next方法才会开始执行生成器函数;
- 在生成器函数内部可以使用yield关键字向外返回一个值;(类似于return)
- 我们可以在next方法返回的对象中拿到这个值{value:’返回值’,done:false};(done表示这个生成器是否全部执行完毕)
- yield不像return一样立即结束而是暂停函数执行;
- 继续调用生成器对象的next方法才会继续执行;
- 调生成器对象的next方法时如果传入一个参数的话,这个值就会作为yield语句的返回值,yield的左边可以接收到这个值;
- 如果没有参数,yield的左边就会收到一个undefined; ```javascript // 生成器函数回顾 function* foo() { console.log(‘start’) const res = yield ‘foo’ console.log(res) }
// 调用生成器函数不会去执行函数,而是会得到一个生成器对象; const generator = foo()
// 调用生成器对象的next方法才会开始执行生成器函数; const result = generator.next() // start console.log(result) // {value: “foo”, done: false}
// yield不像return一样立即结束而是暂停函数执行; // 继续调用生成器对象的next方法才会继续执行; // 调生成器对象的next方法时如果传入一个参数的话,这个值就会作为yield语句的返回值,yield的左边可以接收到这个值; generator.next(‘bar’) // res bar
// 如果没有参数,yield的左边就会收到一个undefined; generator.next() // undefined
yield关键字是在生成器函数里面 向外返回一个值,用外面的 生成器对象的next方法 获取这个值;<br />而外面的生成器对象的next方法的参数会进入到生成器函数,作为yield的结果被左边的变量接收;<br />即:yield向外返回,由next接收;next向内传入,由yield左侧接收;<a name="9wbJN"></a>### 捕获异常调用生成器对象的throw方法也可以让生成器函数继续往下执行,不过它的作用是向内抛入一个异常,生成器函数继续执行就会得到这个异常```javascriptfunction* foo() {console.log('start')try {const res = yield 'foo'// throw向内传入异常,可由内部的try catch捕获;// 因为出现异常,yield左侧的变量声明也不会执行,就直接进入catchconsole.log('res', res)} catch (e) {console.log(e)}}const generator = foo()const result = generator.next() // startconsole.log(result) // {value: "foo", done: false}generator.throw(new Error('Generator error'))// Error: Generator error
Generator 应用
发号器
使用 Generator 函数实现 iterator 方法
// Generator 应用// 案例1:发号器function * createIdMaker () {let id = 1while (true) {yield id++}}const idMaker = createIdMaker()console.log(idMaker.next().value)console.log(idMaker.next().value)console.log(idMaker.next().value)console.log(idMaker.next().value)// 案例2:使用 Generator 函数实现 iterator 方法const todos = {life: ['吃饭', '睡觉', '打豆豆'],learn: ['语文', '数学', '外语'],work: ['喝茶'],[Symbol.iterator]: function * () {const all = [...this.life, ...this.learn, ...this.work]for (const item of all) {yield item}}}for (const item of todos) {console.log(item)}
Generator 配合 Promise 的异步方案
// Generator 配合 Promise 的异步方案function ajax (url) {return new Promise((resolve, reject) => {var xhr = new XMLHttpRequest()xhr.open('GET', url)xhr.responseType = 'json'xhr.onload = () => {if (xhr.status === 200) {resolve(xhr.response)} else {reject(new Error(xhr.statusText))}}xhr.send()})}function * main () {try {const users = yield ajax('/api/users.json')console.log(users)const posts = yield ajax('/api/posts.json')console.log(posts)const urls = yield ajax('/api/urls11.json')console.log(urls)} catch (e) {console.log(e)}}function co (generator) {const g = generator()function handleResult (result) {if (result.done) return // 生成器函数结束result.value.then(data => {handleResult(g.next(data))}, error => {g.throw(error)})}handleResult(g.next())}co(main)// const g = generator()// const result = g.next()// result.value.then(data => {// const result2 = g.next(data)// if (result2.done) return// result2.value.then(data => {// const result3 = g.next(data)// if (result3.done) return// result3.value.then(data => {// g.next(data)// })// })// })
