ES6中Generator
ES6中Generator
Generator是ES6一个很有意思的特性,也是不容易理解的特性。不同于let/const
提供了块级作用域这样明显的目的,这玩意儿被搞出来到底是干嘛的?
首先我们需要明确一个问题,在JavaScript中,任何一个函数只要开始执行,便无法停止下来直到执行完成(别跟我提debug,你见过哪个用户在使用产品的还得开个debug调试你的代码)。
but,Generator提供这种能力。 看下面代码:
function *g(){
console.log('start');
yield 1;
console.log('middle');
yield 2;
console.log('end');
}
var g1 = g();
console.log(g1.next());
// start
// {value: 1, done: false}
console.log(g1.next());
// middle
// {value: 2, done: false}
console.log(g1.next());
// end
// {value: undefined, done: true}
根据输出结果,我们看到,在函数g
中,碰到yield
关键词,运行的程序会停下来。只有调用 next()
方法,才会继续执行函数g
中的代码。所以函数g
本身有暂停状态。
至此,我们需要知道:
- Generator不是函数,不是函数,不是函数;
- g()不会立即出发执行,而是一上来就暂停,并返回一个Iterator对象;
- 每次g1.next()都会打破暂停状态去执行,直到遇到下一个yield或者return
- 遇到yield时,会执行yeild后面的表达式,并返回执行之后的值,然后再次进入暂停状态,此时done: false。
- 遇到return时,会返回值,执行结束,即done: true
- 每次g.next()的返回值永远都是{value: ... , done: ...}的形式
Generator与异步
既然Generator可以函数停下来,有些脑洞清奇的人,想到了可不可以用Generator处理异步程序。
先看一个传统例子:
function asyn(fn) {
return new Promise((resolve,reject)=>{
setTimeout(()=>{
fn();
resolve(true);
}, 1000);
});
}
function main() {
console.log('start');
asyn(function(d) {
console.log('async one');
asyn(function(d) {
console.log('async two');
console.log('end');
});
});
}
main();
再来看看使用了Generator的异步程序:
function asyn(fn) {
return new Promise((resolve,reject)=>{
setTimeout(()=>{
fn();
resolve(true);
}, 1000);
});
}
co(function*() {
console.log('start');
yield asyn(function(d) {
console.log('async one');
});
yield asyn(function(d) {
console.log('async two');
});
console.log('end');
});
function co(fn) {
return new Promise((resolve,reject)=>{
let g = fn();
onFullfilled();
function onFullfilled() {
let ret = null;
ret = g.next();
next(ret);
}
function next(ret) {
if(ret.done) return resolve(ret.value);
ret.value.then(onFullfilled);
}
} );
}
函数在异步程序没有采用嵌套回调,是直接用同步的方式写了出来。道理大概就是,有两个异步程序,用小明和小红指代它们。小红需要等小明执行完了才可以被执行,那么我们在执行到小明时,暂停程序的运行(通过yield
),等到小明有了返回结果时,再执行后面跟着的小红(next()
)。
在上面的程序中,我们添加了一个co
函数,这个函数的作用是让Generator自动执行下去。直白来说,就是当第一个异步函数返回后,自动调用next()
方法运行后面的代码。
Generator与Koa
Koa是基于Node.js的Web应用框架。在Koa中,处理的异步程序主要是网络请求(HTTP)、文件读取和数据查询。这里面的异步场景较多,如果再加上程序分层,采用传统的callback方式,那回调多了去了。
app.on('get', function(){
auth(function(){
router(function(){
find(function(){
save(function(){
render(function(){
//......
})
})
})
})
})
})
这样写法对于程序维护及其不利,毫无便捷性可言。在有了generator后,我们便可以像上面那种方式来写程序。Koa最初的版本就是通过这种方式,让中间处理程序都转成一个个"yield"(中间件)。通过中间件的形式去处理客户端请求,让开发App应用更加灵活,不受框架自身限制。
在最新的Koa2中,已经抛弃了Genetator,转而使用async/await
。
但是无论采用哪种方式,其本质都是利用了Promise。
原文地址:https://segmentfault.com/a/1190000016707991
ES6中Generator的更多相关文章
- ES6中generator传参与返回值
先看两个例子, 1, function* f() { for(var i=0; true; i++) { var reset = yield i; if(reset) { i = -1; } } } ...
- ES6中的迭代器(Iterator)和生成器(Generator)
前面的话 用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简 ...
- 聊聊ES6中的generator
generatorgenerator(生成器)是ES6标准引入的新的数据类型.一个generator看上去像一个函数,但函数执行中间可以停止. ES6定义generator标准的哥们借鉴了Python ...
- ES6中的迭代器、Generator函数以及Generator函数的异步操作
最近在写RN相关的东西,其中涉及到了redux-saga ,saga的实现原理就是ES6中的Generator函数,而Generator函数又和迭代器有着密不可分的关系.所以本篇博客先学习总结了ite ...
- ES6中的Promise和Generator详解
目录 简介 Promise 什么是Promise Promise的特点 Promise的优点 Promise的缺点 Promise的用法 Promise的执行顺序 Promise.prototype. ...
- ES6中的Generator函数
今天小编发现一个es6中的新概念,同时也接触到了一个新关键字yeild,下面我就简单和大家聊聊es6中的generator函数.大家还可以关注我的微信公众号,蜗牛全栈. 一.函数声明:在functio ...
- ES6中的迭代器(Iterator)和生成器(Generator)(二)
一.内建迭代器 迭代器是ES6的一个重要组成部分,在ES6中,已经默认为许多内建类型提供了内建迭代器,只有当这些内建迭代器无法实现目标时才需要自己创建.通常来说当定义自己的对象和类时才会遇到这种情况, ...
- ES6中的迭代器(Iterator)和生成器(Generator)(一)
用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简化数据操作 ...
- 深入理解 JavaScript 异步系列(3)—— ES6 中的 Promise
第一部分,Promise 加入 ES6 标准 原文地址 http://www.cnblogs.com/wangfupeng1988/p/6515855.html 未经作者允许不得转载! 从 jquer ...
随机推荐
- 【CodeForces - 546C】Soldier and Cards (vector或队列)
Soldier and Cards 老样子,直接上国语吧 Descriptions: 两个人打牌,从自己的手牌中抽出最上面的一张比较大小,大的一方可以拿对方的手牌以及自己打掉的手牌重新作为自己的牌, ...
- 工作中常用css样式总结
一.HTML隐藏文本输入框 有三种方法: 1.<input type="hidden" value=""> 这是对任何元素都起作用的: 2.< ...
- firewall-cmd 使用总结
firewalld的简要说明: firewalld .firewall-cmd .firewall-offline-cmd它们Python脚本,通过定义的在/usr/lib/firewalld下面的x ...
- C++ multiset通过greater、less指定排序方式,实现最大堆、最小堆功能
STL中的set和multiset基于红黑树实现,默认排序为从小到大. 定义三个multiset实例,进行测试: multiset<int, greater<int>> gre ...
- win操作系统段和分页机制
- 跟我一起玩Win32开发(21):复制&粘贴&剪贴板操作
我要提醒一下大家,看了我的博文学到的知识,千万不要用于实际开发,不然你会被你的上司骂:“妈的,这些东西哪来的,从来没有人这样做过.”不信你试试,脑细胞被冻结的经理或者技术总监们肯定会这样说的. 如果是 ...
- Mysql的外键
概念:如果一个实体A的某一字段,刚好指向或引用另一个实体B的主键,那么实体A的这个字段就叫作外键,所以简单来说,外键就是外面的主键,就是其他表的主键. 例: 以上的学生表的班级字段,就是一个外键! 其 ...
- 服务器php-cgi.exe进程过多,导致CPU占用100%的解决方法
再使用iis服务器中经常会出现php-cgi.exe进程过多,导致CPU占用100%,最终造成网站运行过慢甚至卡死的情况,重启iis会好一会,过一段时间久出现这种情况,为什么会出现这种情况呢,应该怎么 ...
- Redis学习笔记1-安装配置
一.Redis安装 Redis官网:http://www.redis.io/download 注意:版本号2.4,2.6,2.8等偶数结尾为稳定版,2.5等为非稳定版本,生成环境应该使用稳定版 下载解 ...
- 在idea启动tomcat出现The JAVA_HOME environment variable is not defined correctly的解决
情况:某套代码是用jdk 1.6编译,然后电脑的JAVA_HOME系统变量配的是jdk1.7的,在tomcat启动时报错 The JAVA_HOME environment variable is n ...