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数组插入一条记录的代码
Aug 30 Javascript
Javascript对象中关于setTimeout和setInterval的this介绍
Jul 21 Javascript
JavaScript获取网页中第一个图片id的方法
Apr 03 Javascript
jQuery监控文本框事件并作相应处理的方法
Apr 16 Javascript
jquery中ajax处理跨域的三大方式
Jan 05 Javascript
JavaScript简单实现弹出拖拽窗口(一)
Jun 17 Javascript
AngularJS入门教程之路由与多视图详解
Aug 19 Javascript
vue2 设置router-view默认路径的实例
Sep 20 Javascript
简述vue路由打开一个新的窗口的方法
Nov 29 Javascript
JS使用对象的defineProperty进行变量监控操作示例
Feb 02 Javascript
vue中created和mounted的区别浅析
Aug 13 Javascript
微信小程序实现拖拽功能
Sep 26 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
模仿OSO的论坛(四)
2006/10/09 PHP
php学习笔记之面向对象编程
2012/12/29 PHP
PHP+MYSQL实现读写分离简单实战
2017/03/13 PHP
ThinkPHP5 的简单搭建和使用详解
2018/11/15 PHP
使用js获取地址栏中传递的值
2013/07/02 Javascript
Jquery选择器中使用变量实现动态选择例子
2014/07/25 Javascript
JavaScript获取按钮所在form表单id的方法
2015/04/02 Javascript
JS验证 只能输入小数点,数字,负数的实现方法
2016/10/07 Javascript
第一次接触神奇的前端框架vue.js
2016/12/01 Javascript
AngularJS 霸道的过滤器小结
2017/04/26 Javascript
CKEditor4配置与开发详细中文说明文档
2018/10/08 Javascript
React+Antd+Redux实现待办事件的方法
2019/03/14 Javascript
vue实现歌手列表字母排序下拉滚动条侧栏排序实时更新
2019/05/14 Javascript
vue 实现 rem 布局或vw 布局的方法
2019/11/13 Javascript
pycharm 使用心得(四)显示行号
2014/06/05 Python
python中的闭包用法实例详解
2015/05/05 Python
一键搞定python连接mysql驱动有关问题(windows版本)
2016/04/23 Python
Python遍历目录中的所有文件的方法
2016/07/08 Python
python 二维数组90度旋转的方法
2019/01/28 Python
python3实现zabbix告警推送钉钉的示例
2019/02/20 Python
python海龟绘图之画国旗实例代码
2020/11/11 Python
针对HTML5的Web Worker使用攻略
2015/07/12 HTML / CSS
H5最强接口之canvas实现动态图形功能
2019/05/31 HTML / CSS
super()与this()的区别
2016/01/17 面试题
业务员岗位职责
2013/11/16 职场文书
小学教师岗位职责
2013/11/25 职场文书
美容师的职业规划书
2013/12/27 职场文书
毕业生的自我评价范文
2013/12/31 职场文书
先进事迹报告会感言
2014/01/24 职场文书
互联网创业计划书的书写步骤
2014/01/28 职场文书
2014年党小组工作总结
2014/12/20 职场文书
班主任培训研修日志
2015/11/13 职场文书
导游词之广州陈家祠
2019/10/21 职场文书
Python连续赋值需要注意的一些问题
2021/06/03 Python
15个值得收藏的JavaScript函数
2021/09/15 Javascript
Android 中的类文件和类加载器详情
2022/06/05 Java/Android