1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 比较express与koa中间件模式的区别与联系

比较express与koa中间件模式的区别与联系

时间:2022-04-15 14:55:23

相关推荐

比较express与koa中间件模式的区别与联系

web前端|js教程

express,中间件,对比

web前端-js教程

本篇文章主要介绍了详解express与koa中间件模式对比,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

dstat 源码,vscode做网站,ubuntu仿真,tomcat资源在线,c sqlite取日期段,帝国cms插件下载,阿波罗是前端框架吗,爬虫爬哪些有用的数据,php js 传递参数,西安seo工具推荐,投注网站源码使用,网页式ppt模板,个人介绍单页模板免费下载lzw

起因

微信夹娃娃源码百度云,ubuntu双系统蓝屏,修改tomcat默认路径,爬虫检测scrapy,php自学教程免费交流,什么是seo怎么做好seolzw

最近在学习koa的使用, 由于koa是相当基础的web框架,所以一个完整的web应用所需要的东西大都以中间件的形式引入,比如koa-router, koa-view等。在koa的文档里有提到:koa的中间件模式与express的是不一样的,koa是洋葱型,express是直线型,至于为什么这样,网上很多文章并没有具体分析。或者简单的说是async/await的特性之类。先不说这种说法的对错,对于我来说这种说法还是太模糊了。所以我决定通过源码来分析二者中间件实现的原理以及用法的异同。

企业网站加公众号管理源码,vscode运行多个实例,Ubuntu xrdp升级,tomcat与cgi,sqlite复制到临时表,我的世界爬虫叫什么名字,打不开 php 网页,亲子学校网站首页seo,我的网站模板下载 迅雷下载,帝国html5图片站模板lzw

为了简单起见这里的express用connect代替(实现原理是一致的)

用法

二者都以官网(github)文档为准

connect

下面是官网的用法:

var connect = require(connect);var http = require(http);var app = connect();// gzip/deflate outgoing responsesvar compression = require(compression);app.use(compression());// store session state in browser cookievar cookieSession = require(cookie-session);app.use(cookieSession({ keys: [secret1, secret2]}));// parse urlencoded request bodies into req.bodyvar bodyParser = require(ody-parser);app.use(bodyParser.urlencoded({extended: false}));// respond to all requestsapp.use(function(req, res){ res.end(Hello from Connect!\n);});//create node.js http server and listen on porthttp.createServer(app).listen(3000);

根据文档我们可以看到,connect是提供简单的路由功能的:

app.use(/foo, function fooMiddleware(req, res, next) { // req.url starts with "/foo" next();});app.use(/bar, function barMiddleware(req, res, next) { // req.url starts with "/bar" next();});

connect的中间件是线性的,next过后继续寻找下一个中间件,这种模式直觉上也很好理解,中间件就是一系列数组,通过路由匹配来寻找相应路由的处理方法也就是中间件。事实上connect也是这么实现的。

app.use 就是往中间件数组中塞入新的中间件。中间件的执行则依靠私有方法 app.handle 进行处理,express也是相同的道理。

koa

相对connect,koa的中间件模式就不那么直观了,借用网上的图表示:

也就是koa处理完中间件后还会回来走一趟,这就给了我们更加大的操作空间,来看看koa的官网实例:

const Koa = require(koa);const app = new Koa();// x-response-timeapp.use(async (ctx, next) => { const start = Date.now(); await next(); const ms = Date.now() - start; ctx.set(X-Response-Time, `${ms}ms`);});// loggerapp.use(async (ctx, next) => { const start = Date.now(); await next(); const ms = Date.now() - start; console.log(`${ctx.method} ${ctx.url} - ${ms}`);});// responseapp.use(async ctx => { ctx.body = Hello World;});app.listen(3000);

很明显,当koa处理中间件遇到await next()的时候会暂停当前中间件进而处理下一个中间件,最后再回过头来继续处理剩下的任务,虽然说起来很复杂,但是直觉上我们会有一种隐隐熟悉的感觉:不就是回调函数吗。这里暂且不说具体实现方法,但是确实就是回调函数。跟async/await的特性并无任何关系。

源码简析

connect与koa中间件模式区别的核心就在于next的实现,让我们简单看下二者next的实现。

connect

connect的源码相当少加上注释也就200来行,看起来也很清楚,connect中间件处理在于proto.handle这个私有方法,同样next也是在这里实现的

// 中间件索引var index = 0function next(err) { // 递增 var layer = stack[index++]; // 交由其他部分处理 if (!layer) { defer(done, err); return; } // route data var path = parseUrl(req).pathname || /; var route = layer.route; // 递归 // skip this layer if the route doesn match if (path.toLowerCase().substr(0, route.length) !== route.toLowerCase()) { return next(err); } // call the layer handle call(layer.handle, route, err, req, res, next); }

删掉混淆的代码后 我们可以看到next实现也很简洁。一个递归调用顺序寻找中间件。不断的调用next。代码相当简单但是思路却很值得学习。

其中 done 是第三方处理方法。其他处理sub app以及路由的部分都删除了。不是重点

koa

koa将next的实现抽离成了一个单独的包,代码更加简单,但是实现了一个貌似更加复杂的功能

function compose (middleware) { return function (context, next) { // last called middleware # let index = -1 return dispatch(0) function dispatch (i) { index = i try { return Promise.resolve(fn(context, function next () { return dispatch(i + 1) })) } catch (err) { return Promise.reject(err) } } }}

看着上面处理过的的代码 有些同学可能还是会不明觉厉。

那么我们继续处理一下:

function compose (middleware) { return function (context, next) { // last called middleware # let index = -1 return dispatch(0) function dispatch (i) { index = i let fn = middleware[i] if (i === middleware.length) { fn = next } if (!fn) return return fn(context, function next () { return dispatch(i + 1) }) } }}

这样一来 程序更加简单了 跟async/await也没有任何关系了,让我们看下结果好了

var ms = [ function foo (ctx, next) { console.log(foo1) next() console.log(foo2) }, function bar (ctx, next) { console.log(ar1) next() console.log(ar2) }, function qux (ctx, next) { console.log(qux1) next() console.log(qux2) }]compose(ms)()

执行上面的程序我们可以发现依次输出:

foo1

bar1

qux1

qux2

bar2

foo2

同样是所谓koa的洋葱模型,到这里我们就可以得出这样一个结论:koa的中间件模型跟async或者generator并没有实际联系,只是koa强调async优先。所谓中间件暂停也只是回调函数的原因(在我看来promise.then与回调其实没有什么区别,甚至async/await也是回调的一种形式)。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。