翼度科技»论坛 编程开发 JavaScript 查看内容

[JS] generator基本使用

3

主题

3

帖子

9

积分

新手上路

Rank: 1

积分
9
next方法与yield关键字

generator函数可以返回一个迭代器,通过next方法切换generator的状态。
generator函数被调用时并不会执行内部的语句,而是返回一个迭代器对象。
迭代器对象首次调用next方法,才开始执行generator函数的语句。
直到遇到yield语句,内部的执行中断,返回yield关键字右侧表达式的值作为迭代器调用next方法的返回值。
yield语句本身没有返回值,由下一次调用next方法时传入参数作为yield的返回值。
  1. function* gen(){
  2.   yield 'hello';
  3.   let msg = yield 'world';
  4.   console.log(msg);
  5.   yield 'end';
  6. }
  7. const g = gen();
  8. console.log(g.next());
  9. console.log(g.next());
  10. console.log(g.next('passing msg'));
  11. console.log(g.next());
复制代码
输出结果
  1. { value: 'hello', done: false }
  2. { value: 'world', done: false }
  3. passing msg
  4. { value: 'end', done: false }
  5. { value: undefined, done: true }
复制代码
throw方法

迭代器对象可以通过调用throw方法向generator函数内部“抛出”异常,在函数内部通过try/catch捕获。
也可以在generator函数内部抛出异常,在调用迭代器方法的位置抛出异常。
向内部抛出异常 - 分类讨论

  • (理想情况)调用iterator.throw(new Error(...))向内部抛出异常,在内部对应的yield表达式使用try/catch捕获异常;
  • 如果函数内部没有捕获异常,那么在iterator.throw()语句所在的位置抛出异常;
  • 如果generator内部和iterator.throw所在位置都没有捕获异常进行处理,那么程序终止;
  • 还没首次执行next就执行throw,直接在外部调用iterator.throw的位置抛出异常。
向外抛出异常
接下来先看一个向外抛出异常的案例代码:
  1. function* gen(){
  2.   yield 1;
  3.   throw new Error('inner error');
  4.   yield 2;        // 不会被执行
  5.   yield 3;        // 不会被执行
  6. }
  7. const g = gen();
  8. let res;
  9. do{
  10.   try{
  11.     res = g.next();
  12.     console.log(res);
  13.   }catch(e){
  14.     console.log(e);        // 捕获到 'inner error'
  15.   }
  16. }while(!res.done);
复制代码
运行结果:
  1. { value: 1, done: false }
  2. Error: inner error
  3. { value: undefined, done: true }
复制代码
解析:在generator内部使用throw关键字抛出异常,外部调用iterator.next的地方捕获异常,由于generator抛出异常,JS引擎会认为这个generator已经运行结束了,后续的yield不会执行,迭代器的done变为true;
return关键字

没有写return语句的 Generator 函数默认在尾部返回undefined。
return关键字会返回右侧表达式的值作为next方法的返回值。
return会终止generator,后续的代码都不会执行了,这个特点和普通函数保持一致。
  1. function* gen(){
  2.   yield 1;
  3.   return 2;
  4.   yield 3;
  5. }
  6. const g = gen();
  7. let res;
  8. do{
  9.   res = g.next();
  10.   console.log(res.value);
  11. }while(!res.done);
复制代码
执行结果
  1. 1
  2. 2
复制代码
return 方法

generator函数返回的迭代器对象还有return方法。
可以在外部手动得到return方法得到的值,并且结束generator。
  1. function* gen(){
  2.   yield 1;
  3.   yield 2;
  4.   yield 3;
  5. }
  6. const g = gen();
  7. console.log(g.next());
  8. console.log(g.return('done'));
  9. console.log(g.next());
复制代码
运行结果
  1. { value: 1, done: false }
  2. { value: 'done', done: true }
  3. { value: undefined, done: true }
复制代码
next、throw、return的共同点

这三个方法的本质是让generator函数恢复执行,并且使用不同的语句替换yield表达式。

  • next()将yield表达式替换成一个值;
  • throw()将yield表达式替换成一个throw语句;
  • return()将yield表达式替换成一个return语句。

来源:https://www.cnblogs.com/feixianxing/p/18300402/javascript-es6-generator-basic-usage
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具