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 蒙版进度条(结合图片)
Mar 10 Javascript
HTML颜色选择器实现代码
Nov 23 Javascript
silverlight线程与基于事件驱动javascript引擎(实现轨迹回放功能)
Aug 09 Javascript
js替代copy(示例代码)
Nov 27 Javascript
jQuery验证插件validation使用指南
Apr 21 Javascript
javascript实现类似于新浪微博搜索框弹出效果的方法
Jul 27 Javascript
JS正则截取两个字符串之间及字符串前后内容的方法
Jan 06 Javascript
老生常谈js中0到底是 true 还是 false
Mar 08 Javascript
Vue中this.$router.push参数获取方法
Feb 27 Javascript
Vue+ElementUI使用vue-pdf实现预览功能
Nov 26 Javascript
浅谈Vue组件单元测试究竟测试什么
Feb 05 Javascript
详解Vue2的diff算法
Jan 06 Vue.js
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
用PHP中的 == 运算符进行字符串比较
2006/11/26 PHP
DedeCms模板安装/制作概述
2007/03/11 PHP
php读取图片内容并输出到浏览器的实现代码
2013/08/08 PHP
PHP的switch判断语句的“高级”用法详解
2014/10/01 PHP
thinkphp文件处理类Dir.class.php的用法分析
2014/12/08 PHP
启用Csrf后POST数据时出现的400错误
2015/07/05 PHP
PHP工程师VIM配置分享
2015/12/15 PHP
js 操作css实现代码
2009/06/11 Javascript
利用js实现选项卡的特别效果的实例
2013/03/03 Javascript
jquery ajax 如何向jsp提交表单数据
2015/08/23 Javascript
Javascript 调用 ActionScript 的简单方法
2016/09/22 Javascript
JavaScript中this的用法实例分析
2016/12/19 Javascript
浅析Angular2子模块以及异步加载
2017/04/24 Javascript
EasyUI实现下拉框多选功能
2017/11/07 Javascript
详解vue-cli快速构建vue应用并实现webpack打包
2017/12/13 Javascript
VueJs组件之父子通讯的方式
2018/05/06 Javascript
深入理解nodejs搭建静态服务器(实现命令行)
2019/02/05 NodeJs
微信小程序picker组件关于objectArray数据类型的绑定方法
2019/03/13 Javascript
Python如何为图片添加水印
2016/11/25 Python
Python数据类型之Dict字典实例详解
2019/05/07 Python
Django保护敏感信息的方法示例
2019/05/09 Python
Python文件路径名的操作方法
2019/10/30 Python
django框架ModelForm组件用法详解
2019/12/11 Python
Python解释器以及PyCharm的安装教程图文详解
2020/02/26 Python
python能自学吗
2020/06/18 Python
python 实现"神经衰弱"翻牌游戏
2020/11/09 Python
构造方法和其他方法的区别?怎么调用父类的构造方法
2013/09/22 面试题
法律专业个人实习自我鉴定
2013/09/23 职场文书
学校食堂采购员岗位职责
2013/12/05 职场文书
应届生自我鉴定
2013/12/11 职场文书
大学生写自荐信的技巧
2014/01/08 职场文书
2014年超市工作总结
2014/11/19 职场文书
农村党员干部承诺书
2015/05/04 职场文书
2016年度员工工作表现评语
2015/12/02 职场文书
react中的DOM操作实现
2021/06/30 Javascript
pandas求平均数和中位数的方法实例
2021/08/04 Python