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的更多相关文章

  1. ES6中generator传参与返回值

    先看两个例子, 1, function* f() { for(var i=0; true; i++) { var reset = yield i; if(reset) { i = -1; } } } ...

  2. ES6中的迭代器(Iterator)和生成器(Generator)

    前面的话 用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简 ...

  3. 聊聊ES6中的generator

    generatorgenerator(生成器)是ES6标准引入的新的数据类型.一个generator看上去像一个函数,但函数执行中间可以停止. ES6定义generator标准的哥们借鉴了Python ...

  4. ES6中的迭代器、Generator函数以及Generator函数的异步操作

    最近在写RN相关的东西,其中涉及到了redux-saga ,saga的实现原理就是ES6中的Generator函数,而Generator函数又和迭代器有着密不可分的关系.所以本篇博客先学习总结了ite ...

  5. ES6中的Promise和Generator详解

    目录 简介 Promise 什么是Promise Promise的特点 Promise的优点 Promise的缺点 Promise的用法 Promise的执行顺序 Promise.prototype. ...

  6. ES6中的Generator函数

    今天小编发现一个es6中的新概念,同时也接触到了一个新关键字yeild,下面我就简单和大家聊聊es6中的generator函数.大家还可以关注我的微信公众号,蜗牛全栈. 一.函数声明:在functio ...

  7. ES6中的迭代器(Iterator)和生成器(Generator)(二)

    一.内建迭代器 迭代器是ES6的一个重要组成部分,在ES6中,已经默认为许多内建类型提供了内建迭代器,只有当这些内建迭代器无法实现目标时才需要自己创建.通常来说当定义自己的对象和类时才会遇到这种情况, ...

  8. ES6中的迭代器(Iterator)和生成器(Generator)(一)

    用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简化数据操作 ...

  9. 深入理解 JavaScript 异步系列(3)—— ES6 中的 Promise

    第一部分,Promise 加入 ES6 标准 原文地址 http://www.cnblogs.com/wangfupeng1988/p/6515855.html 未经作者允许不得转载! 从 jquer ...

随机推荐

  1. 给Clouderamanager集群里安装可视化分析利器工具Hue步骤(图文详解)

    扩展博客 以下,是我在手动的CDH版本,安装Hue. CDH版本大数据集群下搭建Hue(hadoop-2.6.0-cdh5.5.4.gz + hue-3.9.0-cdh5.5.4.tar.gz)(博主 ...

  2. Zookeeper(1、3、5节点)集群安装

    1节点 1 week110的zookeeper的安装 + zookeeper提供少量数据的存储 3节点 hadoop-2.6.0.tar.gz的集群搭建(3节点) hadoop-2.6.0-cdh5. ...

  3. Caffe实战三(依赖包解析及环境配置)

    前面的文章使用的软件环境是开始时通过apt-get命令所安装的,本文将通过编译源码的方式重新配置一个可迁移的软件环境.(参考:<深度学习 21天实战Caffe> 第五天 Caffe依赖包解 ...

  4. flask跨域问题

    在Flask开发RESTful后端时,前端请求会遇到跨域的问题.下面是解决方法: 使用 flask-cors库可以很容易的解决   1 pip install flask-cors 两种方法,一个是全 ...

  5. AtCoder Grand Contest 005 C - Tree Restoring

    题目传送门:https://agc005.contest.atcoder.jp/tasks/agc005_c 题目大意: 给定一个长度为\(N\)的整数序列\(A_i\),问能否构造一个\(N\)个节 ...

  6. Appium + Python自动化 - 元素定位uiautomatorviewer

    元素定位主要介绍如何使用uiautiomatorviewer,通过定位到页面上的元素,然后进行相应的点击等操作.uiautiomatorviewer是android-sdk自带的一个元素定位工具,非常 ...

  7. Oozie是什么?

         但是,一般用Azkaban了.(具体见我写的另一篇博客:) 官网:https://oozie.apache.org/ Oozie is a workflow scheduler system ...

  8. AJPFX总结java InputStream读取数据问题

    1. 关于InputStream.read()     在从数据流里读取数据时,为图简单,经常用InputStream.read()方法.这个方法是从流里每次只读取读取一个字节,效率会非常低.     ...

  9. SpringBoot 2.x (7):拦截器

    类似以前SpringMVC的拦截器,但也有一些区别 SpringBoot的拦截器有两种方式: 第一种方式:过时的方式,适用于SpringBoot1.x的方式 package org.dreamtech ...

  10. 【转】android技术栈

    android技术栈-现有使用的进行一个汇总(初稿) 2017年04月24日 16:19:40 阅读数:2004 android技术栈 开发工具 Android studio 开发语言 Java 自动 ...