koa是由 Express 原班人马打造的新的web框架。套用其官方的说法:Koa 应用是一个包含一系列中间件 generator 函数的对象。 这些中间件函数基于 request 请求以一个类似于栈的结构组成并依次执行。

koa的中间件系统原理:

  Koa的精妙之处就在于其基于promise的中间件系统的实现,避免了免除重复繁琐的回调函数嵌套。Koa的中间件是一系列generator函数的对象,执行起来有点类似于栈的结构,依次执行。从网上找到一张图可以比较形象的说明koa的中间件是如何工作的:

  每个中间件都是generator函数,当一个请求过来的时候,会依次经过各个中间件进行处理,当遇到await next()时,Koa 暂停了该中间件,执行下一个中间件。直到某个中间件不调用下个中间件,即没有处理await next()。则kao会逆序向上依次执行被暂停的中间件的剩余部分逻辑。

  代码实例如下:

 const Koa = require('koa');
const app = new Koa();
/**
* 请求依次进入下面三个中间件
* */
// x-response-time
app.use(async function (ctx, next) {
/**
* 首先获得start时间
* */
const start = new Date();
/**
* 遇到next中间件的调用,则暂停该中间件。执行下一个即logger
* */
await next();
/**
* logger,完全执行之后,继续下面的部分
* */
const ms = new Date() - start;
console.log('X-Response-Time', `${ms}ms`);
/**
* 至此,整个请求执行结束。
* */ });
// logger
app.use(async function (ctx, next) {
const start = new Date();
/**
* 获得start之后,暂停。执行response
* */
await next();
/**
* response执行之后,获得执行权继续执行下面逻辑。
* */
const ms = new Date() - start;
console.log(`${ctx.method} ${ctx.url} - ${ms}`);
/**
* 执行完毕,将执行权交个上个中间件,即x-response-time
* */
};
//response
app.use(async function(ctx,next){
/**
* 执行之后,没有下一个中间件的调用,即 await next();
* 则向上执行logger,余下的部分
* */
ctx.body = 'Hello World';
}) app.listen(3000);

  上面代码执行的顺序为:

  1、请求开始时,请求先经过 x-response-time, 当遇到await next()时,暂停当前调用下个中间件。

  2、logger 中间件执行当遇到await next()时,暂停当前调用下个中间件。

  3、reponse 中间件执行,执行完成,将控制权交给上个中间件即logger。

  4、logger执行await next()后面的逻辑,打印相应信息。完成之后,将控制权交给上个中间件即 x-response-time。

  5、 x-response-time执行剩下的部分,打印相应信息。

  当我们使用koa的时候,应该通过use添加一个中间件,处理相关的任务。注意该中间件也应该按照koa的要求为generator函数的形式。

kao+node-orm2需要注意的部分:

   作为Node.js 的ORM框架orm2也是比较流行的。作为后端开发的时候,与express框架的结合也是比较合适的。如果想要配合koa的使用就要注意一下。

  前面提到的koa的中间件是要求generator函数,起码基于promise。而orm2数据库连接则是原本的回调方式进行的。

  

var orm = require('orm');

orm.connect('mysql://root:password@localhost/test', function(err, db) {
if (err) return console.error('Connection error: ' + err); // connected
// ...
});

  这样两者就不能很好的合并使用了。如果想要同时使用的话,解决方法也是比较鲜明的,如何让orm2处理数据库连接等api以promise的方式暴露出来。

  解决方式还是比较多的,比较方便的是,使用对orm2进行了promise包装的qOrm来代替直接引用orm。然后通过app.use引入即可。这样的话数据库连接中间件的代码可以如下:

 var orm = require('orm');
var qOrm = require('q-orm');
var dbSet = require('../../config/setting'); var connection = null; function setup(db) {
require('../models/demoModel')(qOrm, db);
require('../models/personModel')(qOrm, db);
require('../models/questionModel')(qOrm, db);
}
module.exports = async function (ctx,next) {
if (connection){
await next();
} else{
await qOrm.qConnect(dbSet).then(function(db){
connection = db;
setup(db);
ctx.req.models = db.models;
ctx.req.db = db;
});
await next();
}
};

  使用koa一定要理解koa的基本思想,即通过中间件系统依次处理不同任务。这就要求各部分必须满足koa中间件的要求:中间件为ggenerator,而传统的回调方式进行处理的方法不会返回promise的对象给koa来判断当前处理次序。因此会报Module not found的错,并且提示语也不多。第一次遇到的时候用了好久才找到原因所在,希望其他小伙伴引以为戒,既然使用某个框架一定要遵循其要求。

  

koa中间件系统原理及koa+orm2实践。的更多相关文章

  1. Koa中间件(middleware)级联原理

    前言 上次看到了koa-compose的代码,今天来说一下koa中间件的级联以及工作原理. 中间件工作原理 初始化koa实例后,我们会用use方法来加载中间件(middleware),会有一个数组来存 ...

  2. Koa 中间件的执行

    Node.js 中请求的处理 讨论 Koa 中间件前,先看原生 Node.js 中是如何创建 server 和处理请求的. node_server.js const http = require(&q ...

  3. Koa 中间件的执行顺序

    中间件工作原理 初始化koa实例后,我们会用use方法来加载中间件(middleware),会有一个数组来存储中间件,use调用顺序会决定中间件的执行顺序. 每个中间件都是一个函数(不是函数将报错), ...

  4. koa 中间件

    什么是 Koa 的中间件 通俗的讲:中间件就是匹配路由之前或者匹配路由完成做的一系列的操作,我们就可以 把它叫做中间件. 在express中间件(Middleware)是一个函数,它可以访问请求对象( ...

  5. 【nodejs原理&源码赏析(2)】KOA中间件的基本运作原理

    [摘要] KOA中间件的基本运作原理 示例代码托管在:http://www.github.com/dashnowords/blogs 在中间件系统的实现上,KOA中间件通过async/await来在不 ...

  6. KOA中间件的基本运作原理

    示例代码托管在:http://www.github.com/dashnowords/blogs 博客园地址:<大史住在大前端>原创博文目录 华为云社区地址:[你要的前端打怪升级指南] 在中 ...

  7. 深入解析Koa之核心原理

    这篇文章主要介绍了玩转Koa之核心原理分析,本文从封装创建应用程序函数.扩展res和req.中间件实现原理.异常处理的等这几个方面来介绍,写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参 ...

  8. Koa与Node.js开发实战(2)——使用Koa中间件获取响应时间(视频演示)

    学习架构: 在实战项目中,经常需要记录下服务器的响应时间,也就是从服务器接收到HTTP请求,到最终返回给客户端之间所耗时长.在Koa应用中,利用中间件机制可以很方便的实现这一功能.代码如下所示: 01 ...

  9. Koa - 中间件(理解中间件、实现一个验证token中间件)

    前言 Koa 应用程序是一个包含一组中间件函数的对象,它是按照类似堆栈的方式组织和执行的. 当一个中间件调用 next() 则该函数暂停并将控制传递给定义的下一个中间件.当在下游没有更多的中间件执行后 ...

随机推荐

  1. python中将两个list合并为字典

    两个list合并为字典的代码如下: def Run(): list2 = [1, 2, 3, 4, 5 ]; list3 = ["a", "b", " ...

  2. cocos2dx截整屏、截部分屏

    我的环境是cocos2dx 2.x的版本 [CCRenderTexture] CCRenderTexture这个动态纹理类,顾名思义就是可以动态创建纹理图片. 屏幕截图主要步骤: > 开始截图: ...

  3. delete和delete[]

    c++中对new申请的内存的释放方式有delete和delete[两种方式,到底这两者有什么区别呢? 1.我们通常从教科书上看到这样的说明:delete 释放new分配的单个对象指针指向的内存dele ...

  4. Android 如何保证service在后台不被kill

    Android 其实无法做多绝对的不被后台kill掉,我们只能尽量使用一些操作提升不被kill的机会. 一.onStartCommand方法,返回START_STICKY   START_STICKY ...

  5. 《解决在Word中为汉子插入拼音及音标的问题》

    说明:本人使用的是Word2007版本.以下示例都是基于本人电脑操作.如有疑问,欢迎留言交流. [1]为word中的一些文字添加拼音及音标. [2]开始为文字添加拼音及音标. 选中要添加拼音及音标的文 ...

  6. Python爬虫爬取qq视频等动态网页全代码

    环境:py3.4.4 32位 需要插件:selenium BeautifulSoup xlwt # coding = utf-8 from selenium import webdriverfrom ...

  7. Myeclipse 搭建Java Web 项目:Servlet 《二》

    上一节,我们使用myeclipse部署了web项目,但那部署的为静态的web项目,下面我们来学习编写动态的web项目,编写动态项目必须要用到的为:servlet. Servlet是由sun公司命名的, ...

  8. BZOJ 4089:[Sdoi2015]graft(SDOI 2015 Round 2 Day 2)

    别人家的神选系列,我只会做这道题QAQ 题目描述: 给定一颗树,加上k条边,将n个点染色,相邻两点不同,记颜色为i的又ti个,求$$\frac{\sum_{i=1}^{n} \frac{ti}{i}} ...

  9. AWT与Swing的区别

    AWT 是Abstract Window ToolKit (抽象窗口工具包)的缩写,这个工具包提供了一套与本地图形界面进行交互的接口.AWT 中的图形函数与操作系统所提供的图形函数之间有着一一对应的关 ...

  10. 安居客Android项目架构演进

    入职安居客三年从工程师到Team Leader,见证了Android团队一路走来的发展历程.因此有心将这些记录下来与大家分享,也算是对自己三年来一部分工作的总结.希望对大家有所帮助,更希望能得到大家宝 ...