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 相关文章推荐
JQuery中使用Ajax赋值给全局变量异常的解决方法
Jan 10 Javascript
简单的JavaScript互斥锁分享
Feb 02 Javascript
js/jquery判断浏览器类型的方法小结
May 12 Javascript
js canvas实现擦除动画
Jul 16 Javascript
H5实现中奖记录逐行滚动切换效果
Mar 13 Javascript
纯js代码生成可搜索选择下拉列表的实例
Jan 11 Javascript
css配合JavaScript实现tab标签切换效果
Oct 11 Javascript
Vue一次性简洁明了引入所有公共组件的方法
Nov 28 Javascript
微信小程序地图(map)组件点击(tap)获取经纬度的方法
Jan 10 Javascript
js图片无缝滚动插件使用详解
May 26 Javascript
VSCode 配置uni-app的方法
Jul 11 Javascript
Vue父组件监听子组件生命周期
Sep 03 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 session 错误
2009/05/21 PHP
zf框架db类的分页示例分享
2014/03/14 PHP
PHP+mysql实现的三级联动菜单功能示例
2019/02/15 PHP
15款优秀的jQuery导航菜单插件分享
2011/07/19 Javascript
滚动图片效果 jquery实现回旋滚动效果
2013/01/08 Javascript
JavaScript中检测变量是否存在遇到的一些问题
2013/11/11 Javascript
Jquery 获取对象的几种方式介绍
2014/01/17 Javascript
jquery ajaxSubmit 异步提交的简单实现
2014/02/28 Javascript
JavaScript中String.prototype用法实例
2015/05/20 Javascript
详解AngularJS的通信机制
2015/06/18 Javascript
浅谈jquery中delegate()与live()
2015/06/22 Javascript
基于gulp合并压缩Seajs模块的方式说明
2016/06/14 Javascript
JavaScript实现通过select标签跳转网页的方法
2016/09/29 Javascript
完美解决IE不支持Data.parse()的问题
2016/11/24 Javascript
Javascript 使用ajax与C#获取文件大小实例详解
2017/01/13 Javascript
使用jQuery和ajax代替iframe的方法(详解)
2017/04/12 jQuery
bootstrap日期控件问题(双日期、清空等问题解决)
2017/04/19 Javascript
JavaScrpt判断一个数是否是质数的实例代码
2017/06/11 Javascript
详解JS构造函数中this和return
2017/09/16 Javascript
Vue下的国际化处理方法
2017/12/18 Javascript
浅析Vue项目中使用keep-Alive步骤
2018/07/27 Javascript
vue实现从外部修改组件内部的变量的值
2020/07/30 Javascript
小程序中手机号识别的示例
2020/12/14 Javascript
python实现用户登陆邮件通知的方法
2015/07/09 Python
Python处理PDF及生成多层PDF实例代码
2017/04/24 Python
css3进行截取替代js的substring
2013/09/02 HTML / CSS
CSS3中的@keyframes关键帧动画的选择器绑定
2016/06/13 HTML / CSS
利用Canvas模仿百度贴吧客户端loading小球的方法示例
2017/08/13 HTML / CSS
详解移动端Html5页面中1px边框的几种解决方法
2018/07/24 HTML / CSS
自1926年以来就为冰岛保持温暖:66°North
2020/11/27 全球购物
学期研究性学习个人的自我评价
2014/01/09 职场文书
《一株紫丁香》教学反思
2014/02/19 职场文书
在职证明范本
2015/06/15 职场文书
javascript Number 与 Math对象的介绍
2021/11/17 Javascript
MySQL数据库如何给表设置约束详解
2022/03/13 MySQL
MySQL如何快速创建800w条测试数据表
2022/03/17 MySQL