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多行 ...
随机推荐
- 电脑修改密码后git上传失败Authentication failed
(一)进入控制面板 (二)选择用户账户 (三)选择管理你的凭据 (四)选择Windows凭据 (五)选择git保存的用户信息 (六)选择编辑或者进行删除操作 (七)完成
- 根据设备width(375)动态设置font-size
根据html的font-size使用rem来优化移动端页面 (function () { var w = window, d = document.documentElement, t; var re ...
- Metrics-server插件安装配置
1.创建 metrics-server 使用的证书 vim metrics-server-csr.json { "CN": "aggregator", &quo ...
- 用 ghostscript 转化PDF文件为图片 的参数设置
example: gswin32 -dSAFER -dBATCH -dNOPAUSE -r300 -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -sDEVICE=jp ...
- Web开发敏捷之道应用Rails 进行Web开发(原书第4版)遇到的问题
第11章:建立一个基于Ajax的购物车 原书是这样的: 问题:create.js.rjs rails4算是彻底抛弃rjs了,所以按照书上使用以下代码,是一点作用没有用的. 这里介绍一种方法: 1.在a ...
- PhoenixFD插件流体模拟——UI布局【Preview】详解
Liquid Preview 流体预览 本文主要讲解Preview折叠栏中的内容.原文地址:https://docs.chaosgroup.com/display/PHX3MAX/Liquid+Pr ...
- 【JDBC】java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone.
在使用阿里的druid 时,报了一个异常java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized ...
- java中null是什么,以及使用中要注意的事项
1.null既不是对象也不是一种类型,它仅是一种特殊的值,你可以将其赋予任何引用类型,你也可以将null转化成任何类型,例如: Integer i=null; Float f=null; String ...
- java程序启动redis报错ERR Client sent AUTH, but no password is set
配置文件中注释掉password一句 重启程序即可
- openal在vs2010中的配置
下载openal开发工具:相关资料可以在OpenAL官网http://connect.creativelabs.com/openal/default.aspx上获得.这里下载的SDK为OpenAL11 ...