Koa源码分析(一) -- generator
Abstract
本系列是关于Koa框架的文章,目前关注版本是Koa v1。主要分为以下几个方面:
1. Koa源码分析(一) -- generator
2. Koa源码分析(二) -- co的实现
3. Koa源码分析(三) -- middleware机制的实现
Genetator函数
Generator函数是ES6提供的一种异步编程解决方案,其语法行为完全不同于传统函数。
详细解析可见阮一峰老师的《ECMAScript 6 入门 --- Generator》
语法
两大特征
function关键字与函数名之间的*- 函数体内部使用
yield语句
我们定义一个generatorFunction示例:
function* firstGenerator() {
var one = yield 'one';
console.log(one);
var two = yield 'two';
concole.log(two);
var third = yield 'third';
console.log(third);
return 'over'
}
带有 * 的函数声明就代表 firstGenerator 函数是一个generator函数,函数里面的 yield 关键字可以理解为在当前位置设置断点,这一点如有疑问,可以看后续。
语法行为
那generator函数的语法行为究竟与传统函数不同在哪里呢?下边我们来梳理下generator函数的运行步骤。
var it = firstGenerator();
console.log(it.next(1)); // {value: "one", done: false}
console.log(it.next(2)); // {value: "two", done: false}
console.log(it.next(3)); // {value: "third", done: false}
console.log(it.next(4)); // {value: "over", done: true}
首先通过执行 firstGenerator 函数,我们可以得到一个generator对象 it,它是一个迭代器对象。此时, firstGenerator 函数并未执行,只是返回了迭代器对象 it ,我们可以通过 it 对象中 next 方法触发 firstGenerator 函数开始执行,此时我们调用 it.next(1),注意 next 注入的参数 1 并没有任何效果。当 firstGenerator 函数执行到 yield 语句时,被打了断点,停留在此处,并将 yield 后的变量传递给 it.next(1) 结果对象中的 value 字段,另外其中的 done 字段表示 firstGenerator 函数尚未完全执行完,还停留在断点。以此同时,将执行权交换给 it.next(1)。
执行第二次 it.next(2),执行权再次交给 firstGenerator 函数,并将 next 带入的参数传递给函数中的变量 one,此时输出 2。当运行到 yield 'two' 语句时,再次将执行权返回给 it.next(2) 并传值。
第三次执行 it.next(3)的过程与第二次完全一样。
最后一次执行 it.next(4) 时,在此之前, firstGenerator 函数断点在 var third = yield 'third',当 it.next(4) 将执行权交给 firstGenerator 函数时,将 4 传递给变量 third,此刻输出 4。当执行到 return 语句时,整个函数已经执行完了,并将 'over'传递给 it.next(4) 返回结果中的 value 字段,且 done 字段为 true。若没有 return 语句,则 value 字段返回 null。
这样下来,整个 firstGenerator 整个函数执行完毕。我们可以将Generator函数比喻成懒惰的癞蛤蟆,每次都需要使用it.next()方法戳一下,才会有对应的行动。如果大家了解python中协程的概念,应该很好理解Generator函数的语法行为。
进阶语法
在Generator函数中 yield 的语法,其后边的值也可以是函数、对象等等。 yield 后边可以是另一个Generator对象。
function* subGen() {
console.log('step in sub generator');
var b = yield 'sub 1';
console.log(b);
console.log('step out sub generator');
}
var subGenerator = new subGen();
function* mainGen() {
var a = yield 'main 1';
console.log(a);
var b = yield *subGenerator;
console.log(b);
var c = yield 'main 2';
console.log(c);
return 'over';
}
var it = mainGen();
console.log(it.next(1));
// {value: 'main 1', done: false}
console.log(it.next(2));
// 2
// step in sub generator
// {value: 'sub 1', done: false}
console.log(it.next(3));
// 3
// step out sub generator
// null
// {value: 'main 2', done: false}
console.log(it.next(4));
// 4
// {value: 'over', done: true}
yield 后面跟着 *subGenerator 对象,这等同于断点就进入 subGenerator 的 subGen里面,等待 subGen 全部执行完后再回来继续执行,类似于递归。
直白点说,就是将 subGen 内嵌到 mainGen中。
在subGen函数中的return语句并不会起到断点的作用
结束语
Generator函数作为ES6的新特性,通过它可以很好的解决JavaScript中的恶魔回调问题。Koa框架使用这特性很好组织了异步代码的结构。
Koa源码分析(一) -- generator的更多相关文章
- Koa源码分析(三) -- middleware机制的实现
Abstract 本系列是关于Koa框架的文章,目前关注版本是Koa v1.主要分为以下几个方面: Koa源码分析(一) -- generator Koa源码分析(二) -- co的实现 Koa源码分 ...
- Koa源码分析(二) -- co的实现
Abstract 本系列是关于Koa框架的文章,目前关注版本是Koa v1.主要分为以下几个方面: Koa源码分析(一) -- generator Koa源码分析(二) -- co的实现 Koa源码分 ...
- Node.js躬行记(19)——KOA源码分析(上)
本次分析的KOA版本是2.13.1,它非常轻量,诸如路由.模板等功能默认都不提供,需要自己引入相关的中间件. 源码的目录结构比较简单,主要分为3部分,__tests__,lib和docs,从名称中就可 ...
- koa源码分析
最近项目要使用koa,所以提前学习一下,顺便看了koa框架的源码. 注:源码是koa2.x koa的源码很简洁,关键代码只有4个文件,当然还包括一些依赖npm包 const Koa = require ...
- Node.js躬行记(20)——KOA源码分析(下)
在上一篇中,主要分析了package.json和application.js文件,本文会分析剩下的几个文件. 一.context.js 在context.js中,会处理错误,cookie,JSON格式 ...
- koa2中间件koa和koa-compose源码分析原理(一)
koa是基于nodejs平台的下一代web开发框架,它是使用generator和promise,koa的中间件是一系列generator函数的对象.当对象被请求过来的时候,会依次经过各个中间件进行处理 ...
- co源码分析及其实践
本文始发于我的个人博客,如需转载请注明出处. 为了更好的阅读体验,可以直接进去我的个人博客看. 前言 知识储备 阅读本文需要对Generator和Promise有一个基本的了解. 这里我简单地介绍一下 ...
- koa-convert源码分析
koa-convert最主要的作用是:将koa1包中使用的Generator函数转换成Koa2中的async函数.更准确的说是将Generator函数转换成使用co包装成的Promise对象.然后执行 ...
- 新一代web框架Koa源码学习
此文已由作者张佃鹏授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Koa 就是一种简单好用的 Web 框架.它的特点是优雅.简洁.表达力强.自由度高.本身代码只有1000多行 ...
随机推荐
- python算法之插入排序
插入排序非常类似于整扑克牌.在开始摸牌时,左手是空的,牌面朝下放在桌上.接着,一次从桌上摸起一张牌,并将它插入到左手一把牌中的正确位置上.为了找到这张牌的正确位置,要将它与手中已有的牌从右到左地进行比 ...
- Django12-ModelForm中创建局部钩子和全局钩子
一.局部钩子 命名规则为clean_对象名称,例如上面定义了username.pwd对象,那么可以定义clean_username.clean_pwd的局部钩子进行规则校验 1.例子:定义一个手机号校 ...
- 循环列表最后一条不显示borderBottom
You could achieve this using some logic: return books.map((book, i) => { return( <View style={ ...
- 查询当前局域网下所有IP和物理网卡地址
WIN+R –> 打开cmd 键入 arp -a
- 爬了招聘网站之后,总结Python学习的几点建议
来源商业新知网,原标题::爬了招聘网站之后,给你几点学习Python的建议 Python语言相关的岗位非常多,有运维,有自动化测试,有后端开发,有机器学习,如果想要快速上手,并且有不错的就业,那就推荐 ...
- WEB的数据交互具体流程
前一段时间小小的总结了一下,web的前后交互的各种方式可能没写全,后期再写,话不多说 前端传递数据到servlet,servlet获取数据后操作DAO修改数据库,然后servlet将某些参数返回到前端 ...
- ansible批量自动安装LNMP
- event 事件2
4.事件类型 “DOM3级事件”规定了一下几类事件: 1)UI事件(用户界面事件),当用户与页面元素交互时触发 2)焦点事件,当元素获得或失去焦点时触发 3)鼠标事件,当用户通过鼠标在页面上执行操作时 ...
- centos7 安装memcached
(1)编译安装Memcached 1.51.1 安装依赖包libevent# yum -y install epel-release# yum -y install libevent libevent ...
- 探究编译后,try-with-resources括号中的object是否关闭,以及两种写法编译后的对比
源码(@TargetApi(Build.VERSION_CODES.KITKAT)) public List<T> test1() { String sql = "selxe x ...