ES6 Generator函数的应用实例分析


Posted in Javascript onJune 26, 2019

本文实例讲述了ES6 Generator函数的应用。分享给大家供大家参考,具体如下:

Generator 函数是 一种异步编程解决方案,Generator 函数会返回一个遍历器对象,Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式。

认识generator函数

function * fn() {
 console.log('hello');
 return 'Joh';
}
// 执行fn()时不会直接执行方法体中的代码,它会返回一个指针, 这个指针实现了 interator接口,也就是返回一个interator对象
let it = fn();
// 通过调用next就会执行方法体, 返回结果是 {value:'Joh', done:true}, 其中next返回的是函数体中return的值
let res = it.next();
console.log(res);

generator函数中的yield 与 return

function * fn() {
  // 和yield相配合,把一个generator内部分为几个断点来执行,每个断点就是yield语句
  // 注意 yield和return的区别: yield可以有多个,return只能有1个
  yield 1;
  yield 2;
  yield 3;
  return 4; // 可以没有return值,done为true的value将会是undefined
}
let it = fn();
// 在for-of 循环中只能打印done为false的value值,done为true时,程序终止
for(let v of it) {
  console.log(v); // 分别输出 1 2 3
}

yield 的值与赋值语句

function * fn(_name) {
 let name = yield _name; // yield 的默认值为undefined
 return name;
}
let it = fn('Joh');
console.log(it.next()); // {value:'Joh', done:false}
console.log(it.next('Tom')); // {value:'Tom', done:true} // 此处value应该为undefined,但是通过next参数的形式赋值改变了最后一个值
console.log(it.next('Lily')); // {value: undefined, done:true} // 已经循环完毕,即使传值也是undefined

yield 语句的位置与括号

function sum(a, b) {
 return a + b;
}
function * fn() {
 let res = sum(yield 1, 5 + (yield 3));
 console.log(res);
 console.log('my qq: ' + (yield qq)); // yield 在一个语句中需要括起来
}
fn();

yield 异常捕获

异常捕获的方式1:

function * fn() {
 let qq = yield; // yield 默认返回undefined, 不会抛出异常
 console.log(qq);
}
let g = fn();
g.next(); // 第一个断点没有输出
// g.next('qq 11111'); // 完毕之后传值输出:qq 11111
g.throw('error!'); // Uncaught error!

异常捕获的方式2:

function * fn() {
 let qq;
 try {
  qq = yield; // yield 默认返回undefined
 }catch(e){
  console.log('qq have error');
 }finally{
  console.log(qq);
 }
}
let g = fn();
g.next();
g.throw('error!');
// qq have error
// undefined

异常捕获的方式3:

function * fn() {
 let qq;
 qq = yield;
 console.log(qq);
}
let g = fn();
g.next();
try{
 g.throw('error!');
}catch(e){
 console.log('qq have error!');
}

异常捕获的方式4:

function * fn() {
 let qq;
 try {
  qq = yield ff; // ff 未定义, 所以qq不会被正确赋值 此处是非 yield 的异常
 }catch(e){
  console.log('err1');
 }
 console.log(qq);
}
let g = fn();
g.next();
g.next('qq 5554');
// err1
// undefined

利用generator和promise结合使用,让异步的逻辑关系,使用同步的方式书写

function asyncF(name) {
 return new Promise(function(resolve){
  setTimeout(function(){
   resolve('my name is ' + name);
  });
 });
}
function * fn() {
 console.log(yield asyncF('Joh'));
}
let gf = fn();
function exec(gf,value) {
 let res = gf.next(value);
 if(!res.done) {
  if(res.value instanceof Promise) {
   res.value.then(function (v) {
    exec(gf, v);
   })
  }else{
   exec(gf, res.value);
  }
 }
}
exec(gf); // my name is Joh

更复杂的写法:

function asyncF(name) {
 return new Promise(function(resolve){
  setTimeout(function(){
   resolve('my name is ' + name);
  });
 });
}
function sum(a, b) {
 return new Promise(function (resolve) {
  setTimeout(function () {
    resolve(a + b);
  });
 })
}
function * fn(name) {
 if((yield sum(3,5)) > 6) {
  console.log(yield asyncF(name));
 }else{
  console.log('error');
 }
}
let gf = fn('Joh');
// generator 执行器 相当于 tj/co 模块
function exec(gf,value) {
 let res = gf.next(value);
 if(!res.done) {
  if(res.value instanceof Promise) {
   res.value.then(function (v) {
    exec(gf, v);
   })
  }else{
   exec(gf, res.value);
  }
 }
}
exec(gf); // my name is Joh

使用纯promise实现:

function asyncF(name) {
 return new Promise(function(resolve){
  setTimeout(function(){
   resolve('my name is ' + name);
  });
 });
}
function sum(a, b) {
 return new Promise(function (resolve) {
  setTimeout(function () {
    resolve(a + b);
  });
 })
}
function fn(name) {
 sum(3,5)
  .then(function (num) {
   if(num > 6) {
    asyncF(name)
     .then(function (v) {
      console.log(v);
     })
   }else{
    console.log('error');
   }
  })
}
fn('Joh');

使用co模块,来代替自己写的执行器

var co = require('co');
function asyncF(name) {
 return new Promise(function(resolve){
  setTimeout(function(){
   resolve('my name is ' + name);
  });
 });
}
function sum(a, b) {
 return new Promise(function (resolve) {
  setTimeout(function () {
    resolve(a + b);
  });
 })
}
function * fn(name) {
 if((yield sum(3,5)) > 6) {
  console.log(yield asyncF(name));
 }else{
  console.log('error');
 }
}
var fnx = co.wrap(fn);
fnx('Joh'); // my name is Joh

更多关于JavaScript相关内容可查看本站专题:《javascript面向对象入门教程》、《JavaScript切换特效与技巧总结》、《JavaScript查找算法技巧总结》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
js innerHTML 的一些问题的解决方法
Jun 22 Javascript
XmlUtils JS操作XML工具类
Oct 01 Javascript
jQuery 获取对象 基本选择与层级
May 31 Javascript
jquery中filter方法用法实例分析
Feb 06 Javascript
jquery.rotate.js实现可选抽奖次数和中奖内容的转盘抽奖代码
Aug 23 jQuery
JavaScript分步实现一个出生日期的正则表达式
Mar 22 Javascript
element-ui 限制日期选择的方法(datepicker)
May 16 Javascript
JavaScript闭包原理与用法实例分析
Aug 10 Javascript
小程序清理本地缓存的方法
Aug 17 Javascript
JS调用安卓手机摄像头扫描二维码
Oct 16 Javascript
ES6 如何改变JS内置行为的代理与反射
Feb 11 Javascript
layui加载表格,绑定新增,编辑删除,查看按钮事件的例子
Sep 06 Javascript
vue实现简单的日历效果
Sep 24 #Javascript
vue实现记事本功能
Jun 26 #Javascript
ES6 Set结构的应用实例分析
Jun 26 #Javascript
vue.js实现备忘录demo
Jun 26 #Javascript
ES6 Map结构的应用实例分析
Jun 26 #Javascript
vue实现日历备忘录功能
Sep 24 #Javascript
ES6 Array常用扩展的应用实例分析
Jun 26 #Javascript
You might like
关于IIS php调用com组件的权限问题
2012/01/11 PHP
php调用dll的实例操作动画与代码分享
2012/08/14 PHP
探讨php中遍历二维数组的几种方法详解
2013/06/08 PHP
详解WordPress中给链接添加查询字符串的方法
2015/12/18 PHP
php+ajax无刷新上传图片的实现方法
2016/12/06 PHP
对于Laravel 5.5核心架构的深入理解
2018/02/22 PHP
用Javascript同时提交多个Web表单的方法
2009/12/26 Javascript
详解js中class的多种函数封装方法
2016/01/03 Javascript
jQuery Validation Plugin验证插件手动验证
2016/01/26 Javascript
js实现移动端编辑添加地址【模仿京东】
2017/04/28 Javascript
react native带索引的城市列表组件的实例代码
2017/08/08 Javascript
基于zepto.js实现登录界面
2017/10/09 Javascript
微信小程序实现消息框弹出动画
2020/04/18 Javascript
vue双向绑定数据限制长度的方法
2019/11/04 Javascript
原生JS实现贪吃蛇小游戏
2020/03/09 Javascript
[02:23]2018DOTA2亚洲邀请赛趣味视频——反应测试
2018/04/04 DOTA
python通过urllib2爬网页上种子下载示例
2014/02/24 Python
Python写的一个简单DNS服务器实例
2014/06/04 Python
python访问系统环境变量的方法
2015/04/29 Python
python tensorflow学习之识别单张图片的实现的示例
2018/02/09 Python
python3中的md5加密实例
2018/05/29 Python
Django之PopUp的具体实现方法
2019/08/31 Python
Python使用Pandas读写Excel实例解析
2019/11/19 Python
Python如何使用BeautifulSoup爬取网页信息
2019/11/26 Python
Python实现定时监测网站运行状态的示例代码
2020/09/30 Python
html5文本内容_动力节点Java学院整理
2017/07/11 HTML / CSS
材料物理专业大学毕业生求职信
2013/10/15 职场文书
护理学中专毕业生求职信
2013/11/11 职场文书
汽车维修专业个人求职信范文
2014/01/01 职场文书
护士长竞聘书
2014/03/31 职场文书
青年文明号创建承诺
2014/03/31 职场文书
大学生入党自荐书
2015/03/05 职场文书
小学2016年第十八届推普周活动总结
2016/04/05 职场文书
浅谈Python数学建模之整数规划
2021/06/23 Python
使用HttpSessionListener监听器实战
2022/03/17 Java/Android
使用CSS实现六边形的图片效果
2022/08/05 HTML / CSS