We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
一种异步编程的解决方案,与传统函数的语法、行为完全不同
function 关键字与函数名之间加个 * 号。
function
*
function* gen () {}
内部使用 yield 关键字,执行后返回一个迭代器(Iterator),没错,就是用 next 方法去遍历的迭代器:
yield
Iterator
next
function* gen () { yield 1 yield 1 + 1 return 3 } // Iterator const it = gen() it.next() // { value: 1, done: false } it.next() // { value: 2, done: false } it.next() // { value: 3, done: true }
可以使函数“暂停”在某个阶段,等到执行了 next 方法后再继续执行。
Generator 函数返回的迭代器在没有执行 next 是不会执行的:
function* gen () { console.log('executed') } const it = gen() it.next() // executed
另外注意, yield 关键字在其他表达式中,需要用括号包起来,不然会报错:
function* demo() { console.log('Hello' + yield); // SyntaxError console.log('Hello' + yield 123); // SyntaxError console.log('Hello' + (yield)); // OK console.log('Hello' + (yield 123)); // OK }
既然是 Iterator ,就可以用 for...of 循环来遍历它:
for...of
function* gen () { yield 1 yield 2 yield 3 return 4 } for (let value of gen()) { console.log(value) } // 1 2 3 // 注意, `for...of` 循环不会输出结果为 `done: true` 的值
在执行 next 时,如果给它传一个参数,这个参数会作为上一个 yield 表达式的返回值。
如果不传,其实就相当于传了 undefined
undefined
function* gen () { const i = yield 1 console.log(i) yield i + 1 } const it = gen() const y1 = it.next() // { value: 1, done: false } it.next(y1.value + 1) // 函数内部输出 2 // next 返回值: { value: 3, done: false } it.next() // { value: undefined, done: true }
可以在 Generator 函数内部抛出一个错误,如果 Generator 内部没有处理,则会抛出到外部:
function* gen () { try { yield } catch (e) { console.log('Generator 函数内部捕获', e) } } const it = gen() it.next() // 先执行到第一个 yield 处 it.throw('手动抛出一个错误') // Generator 函数内部捕获 手动抛出一个错误
相当于提前把这个迭代器结束遍历,即返回的 done 变为 true
done
true
function* gen () { yield 1 yield 2 yield 3 return 4 } const it = gen() it.next() // { value: 1, done: false } it.return() // { value: undefined, done: true } it.next() // { value: undefined, done: true }
return 的第一个参数可以指定 value 的值:
return
function* gen () { yield 1 yield 2 yield 3 return 4 } const it = gen() it.next() // { value: 1, done: false } it.return('foo') // { value: 'foo', done: true } it.next() // { value: undefined, done: true }
三个函数其实可以理解为,把执行函数时起点的 yield 替换成了不同的语句:
function* gen () { const r = yield 1 } const it = gen() it.next() // 执行到第一个 yield it.next() // 相当于把 `const r = yield 1` 替换成 `const r = undefined` // it.throw(new Error('error')) // 相当于把 `const r = yield 1` 替换成 `const r = throw new Error('error')` // it.return(6) // 相当于把 `const r = yield 1` 替换成 `const r = return 6`
如果在 Generator 函数内部调用 Generator 函数,可以用 yield* 表达式,这样外层在遍历 Generator 时,遇到内部的 Generator 函数,会转而进入内部函数遍历,不会跳过:
yield*
function* bar () { yield 1 yield 2 } function* foo () { yield 3 // 这边如果没有手动去遍历 `bar()` 返回的迭代器, `foo` 的下一个 `next` 函数就会执行到 `yield 4` 了 bar() yield 4 } const it = foo() for (let value of it) { console.log(value) } // 3 4
手动遍历:
function* bar () { yield 1 yield 2 } function* foo () { yield 3 for (let value of bar()) { yield value } yield 4 } const it = foo() for (let value of it) { console.log(value) } // 3 1 2 4
使用 yield* 表达式:
function* bar () { yield 1 yield 2 } function* foo () { yield 3 yield* bar() yield 4 } const it = foo() for (let value of it) { console.log(value) } // 3 1 2 4
Generator 函数作为对象属性的写法:
const obj = { * generatorProperty () { yield 1 } }
由于 Generator 函数返回的是一个 Iterator ,而不是 this 对象,因此在 Generator 函数内绑定在 this 上的属性都是无效的:
this
function* gen () { this.a = 1 } const it = gen() console.log(it instanceof gen) // true , 这是 ES6 规定的,返回的迭代器是 Generator 函数的实例 console.log(it.a) // undefined
此外, Generator 函数也不能作为构造函数而使用 new 命令:
new
function* gen () { this.a = 1 } const it = new gen() // TypeError: gen is not a constructor
这部分见峰哥的文章吧。
http://es6.ruanyifeng.com/#docs/generator
The text was updated successfully, but these errors were encountered:
No branches or pull requests
概念
一种异步编程的解决方案,与传统函数的语法、行为完全不同
语法
function
关键字与函数名之间加个*
号。内部使用
yield
关键字,执行后返回一个迭代器(Iterator
),没错,就是用next
方法去遍历的迭代器:可以使函数“暂停”在某个阶段,等到执行了
next
方法后再继续执行。Generator 函数返回的迭代器在没有执行
next
是不会执行的:另外注意,
yield
关键字在其他表达式中,需要用括号包起来,不然会报错:for...of 循环
既然是 Iterator ,就可以用
for...of
循环来遍历它:next 函数的参数
在执行
next
时,如果给它传一个参数,这个参数会作为上一个yield
表达式的返回值。如果不传,其实就相当于传了
undefined
Generator.prototype.throw()
可以在 Generator 函数内部抛出一个错误,如果 Generator 内部没有处理,则会抛出到外部:
Generator.prototype.return()
相当于提前把这个迭代器结束遍历,即返回的
done
变为true
return
的第一个参数可以指定 value 的值:next, throw, return
三个函数其实可以理解为,把执行函数时起点的
yield
替换成了不同的语句:yield* 表达式
如果在 Generator 函数内部调用 Generator 函数,可以用
yield*
表达式,这样外层在遍历 Generator 时,遇到内部的 Generator 函数,会转而进入内部函数遍历,不会跳过:手动遍历:
使用
yield*
表达式:作为对象属性
Generator 函数作为对象属性的写法:
this
由于 Generator 函数返回的是一个 Iterator ,而不是 this 对象,因此在 Generator 函数内绑定在
this
上的属性都是无效的:此外, Generator 函数也不能作为构造函数而使用
new
命令:Generator 与协程、上下文,应用
这部分见峰哥的文章吧。
参考
http://es6.ruanyifeng.com/#docs/generator
The text was updated successfully, but these errors were encountered: