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. 电脑修改密码后git上传失败Authentication failed

    (一)进入控制面板 (二)选择用户账户 (三)选择管理你的凭据 (四)选择Windows凭据 (五)选择git保存的用户信息 (六)选择编辑或者进行删除操作 (七)完成

  2. 根据设备width(375)动态设置font-size

    根据html的font-size使用rem来优化移动端页面 (function () { var w = window, d = document.documentElement, t; var re ...

  3. Metrics-server插件安装配置

    1.创建 metrics-server 使用的证书 vim metrics-server-csr.json { "CN": "aggregator", &quo ...

  4. 用 ghostscript 转化PDF文件为图片 的参数设置

    example: gswin32 -dSAFER -dBATCH -dNOPAUSE -r300 -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -sDEVICE=jp ...

  5. Web开发敏捷之道应用Rails 进行Web开发(原书第4版)遇到的问题

    第11章:建立一个基于Ajax的购物车 原书是这样的: 问题:create.js.rjs rails4算是彻底抛弃rjs了,所以按照书上使用以下代码,是一点作用没有用的. 这里介绍一种方法: 1.在a ...

  6. PhoenixFD插件流体模拟——UI布局【Preview】详解

    Liquid Preview 流体预览  本文主要讲解Preview折叠栏中的内容.原文地址:https://docs.chaosgroup.com/display/PHX3MAX/Liquid+Pr ...

  7. 【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 ...

  8. java中null是什么,以及使用中要注意的事项

    1.null既不是对象也不是一种类型,它仅是一种特殊的值,你可以将其赋予任何引用类型,你也可以将null转化成任何类型,例如: Integer i=null; Float f=null; String ...

  9. java程序启动redis报错ERR Client sent AUTH, but no password is set

    配置文件中注释掉password一句 重启程序即可

  10. openal在vs2010中的配置

    下载openal开发工具:相关资料可以在OpenAL官网http://connect.creativelabs.com/openal/default.aspx上获得.这里下载的SDK为OpenAL11 ...