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. springboot自定义错误页面

    springboot自定义错误页面 1.加入配置: @Bean public EmbeddedServletContainerCustomizer containerCustomizer() { re ...

  2. CentOS7.4安装Java8

    官网下载Jdk8Linux64位版本: 使用MobaXterm工具连接远程Linux系统: 上传刚才下载好的文件到远程系统下 /usr/local/ 文件夹: 先进入压缩包所在目录再输入命令解压jdk ...

  3. JDBC链接oracle数据库

    package test; import java.sql.* ; public class JDBC_Test { //orcl为oracle数据库中的数据库名,localhost表示连接本机的or ...

  4. Check类之duplicate declaration checking/Class name generation/Type Checking

    1.duplicate declaration checking /** Check that variable does not hide variable with same name in * ...

  5. Jfinal本地eclipse+tomcat运行项目时候遇到错误Exception starting filter

    今天想在本地eclipse上启动tomcat让项目在本地运行,但是老是报错类找不到异常. 也可能报其它错误,大概都是classNotFoundException. 九月 19, 2018 5:42:2 ...

  6. Ubuntu-16.04 R 安装及Jupyter notebook 配置

    1. R 安装 通常在Terminal下直接apt-get 即可,在16.10下可以get到R-3.3.1,目前最新好像是 R-3.4.2,可以去官方网站下载源码编译 (https://www.r-p ...

  7. 剑指offer64:滑动窗口的最大值

    题目描述: 给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值.例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4, ...

  8. Nodejs学习笔记(十七)—浮点运算decimal.js

    前言 开发过程中免不了有浮点运算,JavaScript浮点运算的精度问题会带来一些困扰 JavaScript 只有一种数字类型 ( Number ) JavaScript采用 IEEE 754 标准双 ...

  9. import.html 页面导出execl

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  10. Python引用复制,参数传递,弱引用与垃圾回收

    引用 先上个示例: >>> val = [1] >>> val[0] = val >>> val [[...]] 上述代码使val中包含自身,而产 ...