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 相关文章推荐
一个cssQuery对象 javascript脚本实现代码
Jul 21 Javascript
JavaScript经典效果集锦
Jul 06 Javascript
关于JavaScript对象的动态选择及遍历对象
Mar 10 Javascript
jquery跨域请求示例分享(jquery发送ajax请求)
Mar 25 Javascript
js生成随机数的方法实例
Oct 16 Javascript
JavaScript资源预加载组件和滑屏组件的使用推荐
Mar 10 Javascript
Easyui Tree获取当前选择节点的所有顶级父节点
Feb 14 Javascript
JavaScript 有用的代码片段和 trick
Feb 22 Javascript
vue对storejs获取的数据进行处理时遇到的几种问题小结
Mar 20 Javascript
vue项目强制清除页面缓存的例子
Nov 06 Javascript
ES6中的Javascript解构的实现
Oct 30 Javascript
插件导致ECharts被全量引入的坑示例解析
Sep 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
PHP 木马攻击防御技巧
2009/06/13 PHP
使用PHPMYADMIN操作mysql数据库添加新用户和数据库的方法
2010/04/02 PHP
PHP无敌近乎加密方式!
2010/07/17 PHP
PHP获取MAC地址的具体实例
2013/12/13 PHP
zf框架的校验器InArray使用示例
2014/03/13 PHP
memcache一致性hash的php实现方法
2015/03/05 PHP
学习php设计模式 php实现合成模式(composite)
2015/12/08 PHP
PHP汉字转换拼音的函数代码
2015/12/30 PHP
小程序微信支付功能配置方法示例详解【基于thinkPHP】
2019/05/05 PHP
PHP使用PhpSpreadsheet操作Excel实例详解
2020/03/26 PHP
JAVASCRIPT  THIS详解 面向对象
2009/03/25 Javascript
extjs grid设置某列背景颜色和字体颜色的方法
2010/09/03 Javascript
js表单验证实例讲解
2016/03/31 Javascript
Node.js+Express配置入门教程详解
2016/05/19 Javascript
jquery 将当前时间转换成yyyymmdd格式的实现方法
2016/06/01 Javascript
jQuery实现的简单拖拽功能示例
2016/09/13 Javascript
jquery attr()设置和获取属性值实例教程
2016/09/25 Javascript
node.js版本管理工具n无效的原理和解决方法
2016/11/24 Javascript
Omi v1.0.2发布正式支持传递javascript表达式
2017/03/21 Javascript
Javascript实现基本运算器
2017/07/15 Javascript
vue cli使用绝对路径引用图片问题的解决
2017/12/06 Javascript
使用vue-router beforEach实现判断用户登录跳转路由筛选功能
2018/06/25 Javascript
vue集成kindeditor富文本的实现示例代码
2019/06/07 Javascript
解决layui数据表格table的横向滚动条显示问题
2019/09/04 Javascript
JS实现商品橱窗特效
2020/01/09 Javascript
解决vue初始化项目一直停在downloading template的问题
2020/11/09 Javascript
Python实现周期性抓取网页内容的方法
2015/11/04 Python
django Serializer序列化使用方法详解
2018/10/16 Python
HTML5 贪吃蛇游戏实现思路及源代码
2013/09/03 HTML / CSS
美国家庭鞋店:Shoe Sensation
2019/09/27 全球购物
亿企通软件测试面试题
2012/04/10 面试题
简单叙述一下MYSQL的优化
2016/05/09 面试题
高中地理教学反思
2014/01/29 职场文书
运动会入场词100字
2014/02/06 职场文书
就业推荐表自我评价范文
2015/03/02 职场文书
基于Python和openCV实现图像的全景拼接详细步骤
2021/10/05 Python