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. azkaban架构介绍

    转自:https://blog.csdn.net/huoji1990/article/details/81911904 官网:https://azkaban.readthedocs.io/en/lat ...

  2. node图片资源捉取

    开头先简单说明一下,因为网络资源上最多的资源就是图片,所以在这里也只简单的捉取了图片资源,至于其他的文档,音乐等我是没有试过的.所以暂时还是以图片为案例!!! Step1 首先我们需要加载我们需要的资 ...

  3. node note

    1.关于next() next()函数接受一个Error对象,在判断错误时,返回这个next()函数,并传入自定义的Error对象可以被向下捕捉,你也可以自定义统一捕捉错误Error的中间件,在app ...

  4. Serv-U 配置说明(虚拟路径、网络驱动器、个人文件夹,数据库管理)

    实现效果 1.用户数据存在数据库,可以自己修改. 2.支持匿名用户使用部分功能 3.每个用户均有私人文件夹,可以自己存放文件 4.FTP内主要的文件都在存储内,不存在服务器上 匿名用户访问情况: 普通 ...

  5. Java_监听文件夹或者文件是否有变动

    package org.testWatch.Watch; import java.nio.file.FileSystems; import java.nio.file.Path; import jav ...

  6. MFC新建工程中目录包含中文,资源文件打开失败

    ※尽量不适用中文,各种未知错误,嘿嘿 此方法临时解决问题,可以使程序运行,后续是否还有错误是未知数 需要修改3处位置: 1.资源文件中.rc 右键,点击“查看代码”,找到带中文的资源ID,把中文修改掉 ...

  7. pandas的简单使用

    pandas可以对数据进行整理分析 因为要对excel中的源数据进行分组和处理,所以想到用pandas来处理.试用过确实比自己去读写快捷很多 (实际pandas底层也是用xlrd,xlwt两个第三方包 ...

  8. linux下mycat自启动方法

    每次开机都要启动mycat,网上看了好多都是用shell脚本来实现mycat开机自启动,后来看到一种方法,直接修改系统文件来实现,已经实践过,方法有效. 1.修改脚本文件rc.local:vim /e ...

  9. mysql与cmd,中文乱码

    图中第一次select, 通过navicat插入表中的, 下面的这次select结果,是直接在命令行中插入的,中文就显示了两个问号...搞不懂咋回事..我是win10家庭版系统.....希望各位道友谨 ...

  10. MyCP(课下作业,必做)- 20175218

    MyCP(课下作业,必做) 1.任务详情 编写MyCP.java 实现类似Linux下cp XXX1 XXX2的功能,要求MyCP支持两个参数: java MyCP -tx XXX1.txt XXX2 ...