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 相关文章推荐
javascript学习笔记(二十) 获得和设置元素的特性(属性)
Jun 20 Javascript
jQuery判断checkbox是否选中的小例子
Dec 02 Javascript
JavaScript代码判断点击第几个按钮
Dec 13 Javascript
AngularJS单选框及多选框实现双向动态绑定
Jan 13 Javascript
jQuery基于$.ajax设置移动端click超时处理方法
May 14 Javascript
Canvas 绘制粒子动画背景
Feb 15 Javascript
jquery仿京东侧边栏导航效果
Mar 02 Javascript
vue中render函数的使用详解
Oct 12 Javascript
qrcode生成二维码微信长按无法识别问题的解决
Apr 04 Javascript
详解json串反转义(消除反斜杠)
Aug 12 Javascript
javascript canvas时钟模拟器
Jul 13 Javascript
javascript利用canvas实现鼠标拖拽功能
Jul 23 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
日本十大惊悚动漫
2020/03/04 日漫
配置最新的PHP加MYSQL服务器
2006/10/09 PHP
PHP开发负载均衡指南
2010/07/17 PHP
php版微信公众号接口实现发红包的方法
2016/10/14 PHP
laravel自定义分页效果
2017/07/23 PHP
解决laravel groupBy 对查询结果进行分组出现的问题
2019/10/09 PHP
php 利用socket发送GET,POST请求的实例代码
2020/07/04 PHP
javascript实现的动态文字变换
2007/07/28 Javascript
围观tangram js库
2010/12/28 Javascript
基于jquery的复制网页内容到WORD的实现代码
2011/02/16 Javascript
jQuery获取样式中的背景颜色属性值/颜色值
2012/12/17 Javascript
基于jQuery的JavaScript模版引擎JsRender使用指南
2014/12/29 Javascript
JS Array.slice 截取数组的实现方法
2016/01/02 Javascript
基于javascript实现右下角浮动广告效果
2016/01/08 Javascript
JavaScript实现iframe自动高度调整和不同主域名跨域
2016/02/27 Javascript
JS及PHP代码编写八大排序算法
2016/07/12 Javascript
浅析Node.js实现HTTP文件下载
2016/08/05 Javascript
微信小程序  modal详解及实例代码
2016/11/09 Javascript
原生js实现放大镜效果
2017/01/11 Javascript
VueJs 搭建Axios接口请求工具
2017/11/20 Javascript
详解vue项目中调用百度地图API使用方法
2019/04/25 Javascript
JavaScript中判断为整数的多种方式及保留两位小数的方法
2019/09/09 Javascript
《javascript设计模式》学习笔记七:Javascript面向对象程序设计组合模式详解
2020/04/08 Javascript
Python中pip安装非PyPI官网第三方库的方法
2015/06/02 Python
玩转python爬虫之爬取糗事百科段子
2016/02/17 Python
使用Python来开发微信功能
2018/06/13 Python
Django中自定义admin Xadmin的实现代码
2019/08/09 Python
如何解决django-celery启动后迅速关闭
2019/10/16 Python
pytorch+lstm实现的pos示例
2020/01/14 Python
Trip.com香港网站:Ctrip携程旗下,全球最大的网上旅游社之一
2016/08/01 全球购物
关于Assembly命名空间的三个面试题
2015/07/23 面试题
会计实习期自我鉴定
2013/10/06 职场文书
超市仓管员岗位职责范本
2014/09/18 职场文书
幸福家庭事迹材料
2014/12/20 职场文书
2015年员工工作总结范文
2015/04/08 职场文书
优秀创业计划书分享
2019/07/19 职场文书