Generator

关键词:状态机,遍历器,同步方式写异步方法

基本概念

  • 形式上,Generator函数是一个普通函数,但是有两个特征。

    • function关键字与函数名之间有一个星号。
    • 二是,函数体内部使用yield语句,定义不同的内部状态。
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
var h = helloWorldGenerator();
  • 调用Generator函数,返回一个遍历器对象,代表Generator函数的内部指针。
// 接上面的demo

hw.next()
// { value: 'hello', done: false } hw.next()
// { value: 'world', done: false } hw.next()
// { value: 'ending', done: true } hw.next()
// { value: undefined, done: true }

yield语句

  • yield语句不能用在普通函数中,否则会报错
(function (){
yield 1;
})()
  • yield语句如果用在一个表达式之中,必须放在圆括号里面
console.log('Hello' + yield); // SyntaxError
console.log('Hello' + yield 123); // SyntaxError console.log('Hello' + (yield)); // OK
console.log('Hello' + (yield 123)); // OK
  • yield语句用作函数参数或赋值表达式的右边,可以不加括号
foo(yield 'a', yield 'b'); // OK
let input = yield; // OK

return()

  • 如果主动调用return()方法,Generator函数将被终结
function* gen(){
yield 1;
yield 2;
yield 3;
}
var g = gen();
g.next() // {value: 1, done: false}
g.return('foo') // {value: 'foo', done: true}
g.next() // {value: undefined, done: true}
  • 但是,如果Generator函数内部有try...finally代码块,那么return方法会推迟到finally代码块执行完再执行。
function* gen(){
try{
yield 1;
}finally{
yield 2;
}
yield 3;
}
var g = gen();
g.next() // {value: 1, done: false}
g.return(10) // {value: 2, done: false}
g.next() // {value: 10, done: true}

yield*

  • 在一个Generater函数内部直接调用另外一个Generater函数无效
function* outer(){
yield 1;
yield inner();
return 3;
}
function* inner(){
yield 2;
}
var o = outer();
o.next(); // {value: 1, done: false}
o.next(); // {value: inner, done: false}
o.next(); // {value: 3, done: true}
  • 上面的情况可以使用yield*解决
function* outer(){
yield 1;
yield* inner(); // 调用方法与上面不同
return 3;
}
function* inner(){
yield 2;
}
var o = outer();
o.next(); // {value: 1, done: false}
o.next(); // {value: 2, done: false} // 返回结果与上面不同
o.next(); // {value: 3, done: true}
  • 任何数据结构只要有Iterator接口,就可以被yield*遍历。
function* demo(){
yield* [1, 2, 3];
}
var d = demo();
d.next(); // {value: 1, done: false}
d.next(); // {value: 2, done: false}
d.next(); // {value: 3, done: false}
d.next(); // {value: undefined, done: true}
  • 如果被代理的Generator函数有return语句,那么就可以向代理它的Generator函数返回数据。
function* outer(){
yield 1;
var i = yield* inner();
yield 2 + i;
}
function* inner(){
return 2;
}
var o = outer();
o.next(); // {value: 1, done: false}
o.next(); // {value: 4, done: false}

作为对象属性的Generator函数

  • 如果一个对象的属性是Generator函数,可以简写成下面的形式。
let obj = {
* gen(){
yield 1;
}
};
var g = obj.gen();
g.next(); // {value: 1, done: false}

Generator函数的this

应用

  • 异步操作的同步化表达,逻辑更清晰
function* render(){
showLoading();
var res = yield getData();
hideLoading();
console.log(res); // 打印ajax的结果
}
function getData(){
$.ajax().done(function(res){
r.next(res);
});
}
var r = render();
r.next();
  • 控制流管理,摆脱回调函数多层嵌套
// callback方式
function step(){
step1(function(res1){
step2(res1, function(res2){
step3(res2, function(res3){
console.log(res3);
})
})
})
}
// promise方式
function step(){
step1()
.then(step2)
.then(step3)
.then(function({
// do something
}))
}
// Generator方式
function step(){
var res1 = yield step1();
var res2 = yield step2(res1);
var res3 = yield step3(res2);
}
  • 多任务并行。如果yield语句后面的参数,是一个具有遍历器接口的对象,yield会遍历这个对象,再往下执行。这意味着,多个任务按顺序一个接一个执行时,yield语句可以按顺序排列。多个任务需要并列执行时(比如只有A任务和B任务都执行完,才能执行C任务),可以采用数组的写法。
function execTaskA(){
return new Promise(function(resolve, reject){
if(true){
resolve('a')
}
})
}
function execTaskB(){
return new Promise(function(resolve, reject){
if(true){
resolve('b')
}
})
}
function* execTasks(){
var [resA, resB] = yield [execTaskA(), execTaskB()];
// let resB = yield* execTaskB();
console.log(resA, resB);
}
var t = execTasks();
t.next();
  • 关于Generator函数的自动执行,可以关注github上的co组件

ES6-Generator的更多相关文章

  1. es6 generator函数的异步编程

    es6 generator函数,我们都知道asycn和await是generator函数的语法糖,那么genertaor怎么样才能实现asycn和await的功能呢? 1.thunk函数    将函数 ...

  2. ES6 Generator vs ES6 async/await

    ES6 Generator vs ES6 async/await next yield promise refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允 ...

  3. es6 generator函数

    es6 新增了Generator函数,一种异步编程的解决方案 回顾一下,es6 提供了新的遍历方法,for of ,适用于各种数据集合,统一了遍历操作,原生支持for of 集合的数据集合有.数组,字 ...

  4. ES6 Generator的应用场景

    一.基础知识 API文档 ES6 诞生以前,异步编程的方法,大概有下面四种. 回调函数 事件监听 发布/订阅 Promise 对象 Generator 函数将 JavaScript 异步编程带入了一个 ...

  5. ES6 Generator async

    Generator 函数是 ES6 提供的一种异步编程解决方案 async 函数使得异步操作变得更加方便,是 Generator 函数的语法糖. js单线程的原因是:避免DOM渲染冲突! 更新:201 ...

  6. ES6 Generator 学习笔记一

    Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同. Generator 函数有多种理解角度.从语法上,首先可以把它理解成,Generator 函数是一个状态机 ...

  7. ES6 generator 基础

    参考文档 harmony:generators Generator是ES6的新特性,通过yield关键字,可以让函数的执行流挂起,那么便为改变执行流程提供了可能. 创建Generator functi ...

  8. ES6:Generator函数(1)

    Generator函数是ES6提供的一种异步编程解决方案.它会返回一个遍历器对象 function* helloWorldGenerator(){ yield “hello”; yield “worl ...

  9. es6 --- Generator 函数

    第一部分,ES6 中的 Generator 在 ES6 出现之前,基本都是各式各样类似Promise的解决方案来处理异步操作的代码逻辑,但是 ES6 的Generator却给异步操作又提供了新的思路, ...

  10. ES6 Generator使用

    // generator介绍: function* hello() { console.log("hello world") } hello();//没有执行 // 直接调用hel ...

随机推荐

  1. (转)Python - 字符串对齐

    https://zhuanlan.zhihu.com/p/33923344-----------Python小知识:用format格式化输出字符串 版权声明:本文为博主原创文章,未经博主允许不得转载. ...

  2. (转)解锁MySQL备份恢复的4种正确姿势

    本文根据DBAplus社群第104期线上分享整理而成. 原文:http://dbaplus.cn/news-11-1267-1.html 讲师介绍   冯帅 点融网高级DBA 获有Oracle OCM ...

  3. Linux 删除文件夹和文件的命令(转载)

    Linux 删除文件夹和文件的命令 听语音 | 浏览:93339 | 更新:2013-05-02 18:40 | 标签:linux 文件夹 linux删除目录很简单,很多人还是习惯用rmdir,不过一 ...

  4. 【数组】Maximum Subarray

    题目: Find the contiguous subarray within an array (containing at least one number) which has the larg ...

  5. mysql 一个表内根据字段对应值不同查询统计总数

  6. Flow中的Switch分析

    A switch statement can complete normally iff at least one of the following is true: (1)The switch bl ...

  7. 【好书分享】容器网络到kubernetes网络

    Nginx 公司的 Michael Hausenblas 发布了一本关于 docker 和 kubernetes 中的容器网络的小册子.这份资料一共 72 页,是大家由浅入深的了解 Docker 和 ...

  8. SpringMVC源码阅读:定位Controller

    1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码分析,弄清楚Spr ...

  9. [WC 2018]州区划分

    Description 题库链接 小 \(S\) 现在拥有 \(n\) 座城市,第 \(i\) 座城市的人口为 \(w_i\) ,城市与城市之间可能有双向道路相连. 现在小 \(S\) 要将这 \(n ...

  10. web前端--实现前后端分离的心得

    1.实现前后端分离的心得 2.前后端分离实践 3.谈谈前后端的分工协作 4.从MVC到前后端分离(REST-个人也认为是目前比较流行和比较好的方式) 4.1.REST风格框架实战:从MVC到前后端分离 ...