Abstract

本系列是关于Koa框架的文章,目前关注版本是Koa v1。主要分为以下几个方面:

1. Koa源码分析(一) -- generator

2. Koa源码分析(二) -- co的实现

3. Koa源码分析(三) -- middleware机制的实现

Genetator函数

Generator函数是ES6提供的一种异步编程解决方案,其语法行为完全不同于传统函数。

详细解析可见阮一峰老师的《ECMAScript 6 入门 --- Generator》

语法

两大特征

  1. function 关键字与函数名之间的 *
  2. 函数体内部使用 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 对象,这等同于断点就进入 subGeneratorsubGen里面,等待 subGen 全部执行完后再回来继续执行,类似于递归。

直白点说,就是将 subGen 内嵌到 mainGen中。

subGen函数中的return语句并不会起到断点的作用

结束语

Generator函数作为ES6的新特性,通过它可以很好的解决JavaScript中的恶魔回调问题。Koa框架使用这特性很好组织了异步代码的结构。

Koa源码分析(一) -- generator的更多相关文章

  1. Koa源码分析(三) -- middleware机制的实现

    Abstract 本系列是关于Koa框架的文章,目前关注版本是Koa v1.主要分为以下几个方面: Koa源码分析(一) -- generator Koa源码分析(二) -- co的实现 Koa源码分 ...

  2. Koa源码分析(二) -- co的实现

    Abstract 本系列是关于Koa框架的文章,目前关注版本是Koa v1.主要分为以下几个方面: Koa源码分析(一) -- generator Koa源码分析(二) -- co的实现 Koa源码分 ...

  3. Node.js躬行记(19)——KOA源码分析(上)

    本次分析的KOA版本是2.13.1,它非常轻量,诸如路由.模板等功能默认都不提供,需要自己引入相关的中间件. 源码的目录结构比较简单,主要分为3部分,__tests__,lib和docs,从名称中就可 ...

  4. koa源码分析

    最近项目要使用koa,所以提前学习一下,顺便看了koa框架的源码. 注:源码是koa2.x koa的源码很简洁,关键代码只有4个文件,当然还包括一些依赖npm包 const Koa = require ...

  5. Node.js躬行记(20)——KOA源码分析(下)

    在上一篇中,主要分析了package.json和application.js文件,本文会分析剩下的几个文件. 一.context.js 在context.js中,会处理错误,cookie,JSON格式 ...

  6. koa2中间件koa和koa-compose源码分析原理(一)

    koa是基于nodejs平台的下一代web开发框架,它是使用generator和promise,koa的中间件是一系列generator函数的对象.当对象被请求过来的时候,会依次经过各个中间件进行处理 ...

  7. co源码分析及其实践

    本文始发于我的个人博客,如需转载请注明出处. 为了更好的阅读体验,可以直接进去我的个人博客看. 前言 知识储备 阅读本文需要对Generator和Promise有一个基本的了解. 这里我简单地介绍一下 ...

  8. koa-convert源码分析

    koa-convert最主要的作用是:将koa1包中使用的Generator函数转换成Koa2中的async函数.更准确的说是将Generator函数转换成使用co包装成的Promise对象.然后执行 ...

  9. 新一代web框架Koa源码学习

    此文已由作者张佃鹏授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Koa 就是一种简单好用的 Web 框架.它的特点是优雅.简洁.表达力强.自由度高.本身代码只有1000多行 ...

随机推荐

  1. 魔力Python——对象

    Python之中,一切皆对象. 本文分为4部分: 1. 面向对象:初识 2. 面向对象:进阶 3. 面向对象:三大特性----继承,多态,封装 4. 面向对象:反射 0. 楔子 面向过程和面向对象的是 ...

  2. SpringBoot学习笔记1

    1.什么是SpringBoot 用一些固定的方式来构建生产级别的spring应用.spring boot推崇约定大于配置的方式便于你能够快速的启动并运行程序. 2.为什么要学spring boot j ...

  3. cenos 修改静态ip

    修改为静态ip 1)在终端命令窗口中输入 [root@hadoop101 /]#vim /etc/udev/rules.d/70-persistent-net.rules 进入如下页面,删除eth0该 ...

  4. React State(状态)

    function FormattedDate(props){ return ( <h1>现在是{props.date}</h1> ) } class Clock extends ...

  5. fibonacci数列-斐波那契数列-python编程

    未完待续~ 了解fibonacci数列: 斐波纳契数列(Fibonacci Sequence),又称黄金分割数列. 1,1,2,3,5,8,13,21,34,55,89,144,233,377,610 ...

  6. Django07-cookie和session

    一.Cookie 1.Cookie的由来 大家都知道HTTP协议是无状态的.无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响 ...

  7. KeyValuePair 和 Dictionary 的关系和区别

    KeyValuePair 和 Dictionary 的关系 1.KeyValuePair      a.KeyValuePair 是一个结构体(struct):     b.KeyValuePair  ...

  8. linux dd 本地挂载

    losetup /dev/loop0 /root/test.img mkfs.ext4 /dev/loop0 mount /dev/loop0 /data

  9. CNN中feature map、卷积核、卷积核个数、filter、channel的概念解释,以及CNN 学习过程中卷积核更新的理解

    具体可以看这篇文章,写的很详细.https://blog.csdn.net/xys430381_1/article/details/82529397

  10. TOMCAT程序的层级目录

    web | |---------js,jsp,html,css(资源文件在web根目录下面 可以被浏览器直接访问) |---------WEB-INF(配置文件web.xml   lib---jar ...