关于express与koa的使用对比详解

前言

提到Node.js开发,不得不提目前炙手可热的2大框架express和koa。Express诞生已有时日,是一个简洁而灵活的web开发框架,使用简单而功能强大。Koa相对更为年轻,是Express框架原班人马基于ES6新特性重新开发的敏捷开发框架,现在可谓风头正劲,大有赶超Express之势。

Express和koa都是服务端的开发框架,服务端开发的重点是对HTTP Request和HTTP Response两个对象的封装和处理,应用的生命周期维护以及视图的处理等。

Express主要基于Connect中间件框架,功能丰富,随取随用,并且框架自身封装了大量便利的功能,比如路由、视图处理等等。而koa主要基于co中间件框架,框架自身并没集成太多功能,大部分功能需要用户自行require中间件去解决,但是由于其基于ES6 generator特性的中间件机制,解决了长期诟病的“callback hell”和麻烦的错误处理的问题,大受开发者欢迎。

以前其实写过一篇express和koa的对比, 但是后来发现里面有不少谬误. 所以一直惦记着纠正一下之前的错误, 尤其关于中间件部分的对比.

这里的express就拿更加简单的connect代替

connect的执行流程
通常我们都说connect的中间件模型是线性的, 也就是一个一个往下执行的, 如下图:

这么说当然是没错的, 但是当我们执行下面代码的时候可能会有那么一点小小的困惑:

const connect = require('connect')
const app = connect()
app.use(function m1 (req, res, next) {
 console.log('m1')
 next()
 console.log('m1 end')
})
app.use(function m2 (req, res, next) {
 console.log('m2')
 next()
 console.log('m2 end')
})
app.use(function m3 (req, res, next) {
 console.log('m3')
 res.end('hello')
})
app.listen(8080)

当我们访问http://127.0.0.1:8080的时候, 控制台会打印如下:

m1
m2
m3
m2 end
m1 end

这么个结果跟我们上面的模型似乎有点出入, 不是说线性的吗, 为什么next后面的代码还会继续执行? 当然这个我们再之前已经有过结论了, 有兴趣的可以详细瞧瞧, 我们现在直接拿来结果, connect的中间件模型伪代码表示如下:

http.createServer(function (req, res) {
 m1 (req, res) {
 m2 (req, res) {
 m3 (req, res) {}
 }
 }
})

可以看到就是一层一层嵌套的回调, 那么再把我们之前有点疑问的代码简化一下:

http.createServer(function (req, res) {
 console.log('m1')
 m1 (req, res) {
 console.log('m2')
 m2 (req, res) {
 m3 (req, res) {
 console.log('m3')
 res.end('hello')
 }
 }
 console.log('m2 end')
 }
 console.log('m1 end')
})

千万别被上面的回调绕晕了, 就是很简单的回调函数, 一切都解释的通了: 即使res.end之后, 我们的代码还是要继续往下走的, 可以这么说connect的中间件其实也是洋葱形的, 但是因为作为同步代码, 一般不回这么做罢了, 那么上面我们可以重现描述一下connect的中间件模型了:

Koa的执行流程

同样我们再Koa源码分析, 也是说过Koa的中间件模型: 洋葱形

以下面代码为例:

const Koa = require('koa')
const app = new Koa()
app.use(async function m1 (ctx, next) {
 console.log('m1')
 await next()
 console.log('m1 end')
})
app.use(async function m2 (ctx, next) {
 console.log('m2')
 await next()
 console.log('m2 end')
})
app.use(async function m3 (ctx) {
 console.log('m3')
 ctx.body = 'hello'
})
app.listen(8080)

访问服务, 输出:

m1
m2
m3
m2 end
m1 end

emm 貌似跟connect没差别, 之前看过一篇文章, 实验到这里得到了一个koa和express的中间件模型没差别的结论, 包括我也是很迷惑, 当然是有差别的, 结论后面讲. 同样这里直接拿出koa中间件的简化模型:

Promise.resolve(async m1 () {
 console.log(m1)
 await Promise.resolve(async m2 () {
 console.log(m2)
 await Promise.resolve(async m3 () {
 console.log(m3)
 ctx.body = 'xxx'
 })
 console.log(m2 end)
 })
 console.log(m1 end)
})

我们知道async/await的作用是'同步化'异步操作(看上去如此, 其实不是, 但是我们不需要去管), 那这里的Promise理所当然的被'同步'了, 也就是说console.log(m3 end)的一切异步操作都可以'同步化'.

结论

说出结论之前我们其实可以想一下, 既然connect的中间件也是洋葱形的, 那么跟koa一样的用法似乎也没啥毛病, 那么我来设想一下, 我们的服务需要取数据库里的的一个用户假设是getUser吧, getUser当然是异步的. 分别来看看connect和koa的做法吧:

// connect
app.use(function (req, res) {
 getUser(user => res.end(user))
})
// Koa
app.use(async (ctx) => {
 const user = await getUser()
 ctx.body = user
})

当然这么看似乎没啥差别. 那直接给出结论吧(憋): connect的中间件是同步, 不会'等'其他异步操作, koa则可以'等'异步操作. 当然你不等也没啥问题.

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

您可能感兴趣的文章:

  • 详解express与koa中间件模式对比
(0)

相关推荐

  • 详解express与koa中间件模式对比

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

  • 关于express与koa的使用对比详解

    前言 提到Node.js开发,不得不提目前炙手可热的2大框架express和koa.Express诞生已有时日,是一个简洁而灵活的web开发框架,使用简单而功能强大.Koa相对更为年轻,是Express框架原班人马基于ES6新特性重新开发的敏捷开发框架,现在可谓风头正劲,大有赶超Express之势. Express和koa都是服务端的开发框架,服务端开发的重点是对HTTP Request和HTTP Response两个对象的封装和处理,应用的生命周期维护以及视图的处理等. Express主要基于

  • Windows系统下nodejs、npm、express的下载和安装教程详解

    1. node.js下载 首先进入http://nodejs.org/dist/,这里面的版本呢,几乎每个月都出几个新的,建议大家下载最新版本,看看自己的电脑是多少位的,别下错了. 下载完解压到你想放的位置就好了,解压后你会发现里面有node.exe.我解压到了D:\software_install文件夹. 接下来去命令行,即点击电脑左下角的开始-->运行-->cmd. 进入node.exe所在的目录,输入node -v,查看你的node版本.我的路径如下图所示: 如果你获得以上输出结果,说明

  • 在python中获取div的文本内容并和想定结果进行对比详解

    div的内容为: <div style="background-color: rgb(255, 238, 221);" id="status" class="errors">您输入的用户名或密码有误.</div> # coding:utf-8 from selenium import webdriver browser = webdriver.Firefox() url = 'file:///C:/Users/li/Des

  • 关于Django ForeignKey 反向查询中filter和_set的效率对比详解

    前言 大家使用 Django 创建模型的时候一定会经常使用 ForeignKey 来创建两个表格之间多对一的外键关系,例如B中有一个 models.ForeignKey(A) .而当我们需要反向查询 A 中某个具体实例所关联的 B 时,可能会用到 A.B_set.all() 或 B.objects.filter(A) 这两种不同的方法. 不知道大家有没有也想过一个问题:当网站实际上线后,SEO强调页面加载速度,而当面对不断增大的请求量,这两种方法的哪一种速度更快? 馆主我产生了这个疑问,所以就打

  • Python 内置函数globals()和locals()对比详解

    这篇文章主要介绍了Python globals()和locals()对比详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Python的两个内置函数,globals()和locals() ,它们提供了基于字典的访问局部和全局变量的方式. globals()是可写的,即,可修改该字典中的键值,可新增和删除键值对. 而locals()是不可修改字典中已存在的键值的,也不能pop移除键值对,但是可以新增键值对. Demo: a = 1 # 定义一个

  • lambda表达式与传统接口函数实现方式对比详解

    目录 在本号之前写过的一些文章中,笔者使用了lambda表达式语法,一些读者反映说代码看不懂.本以为java 13都已经出了,java 8中最重要特性lambda表达式大家应该都掌握了,实际上还是存在大量的程序员没有使用java8,还有的使用了java8也不会使用lambda表达式.所以,写这篇文章还是有必要的,如果您觉得我的文章对您有帮助,期待您的关注. Lambda表达式是Java 8最流行最常用的功能特性.它将函数式编程概念引入Java,函数式编程的好处在于可以帮助我们节省大量的代码,非常

  • Python图像运算之图像灰度直方图对比详解

    目录 一.灰度增强直方图对比 二.灰度减弱直方图对比 三.图像反色直方图对比 四.图像对数变换直方图对比 五.图像阈值化处理直方图对比 六.总结 一.灰度增强直方图对比 图像灰度上移变换使用的表达式为: DB=DA+50 该算法将实现图像灰度值的上移,从而提升图像的亮度,结合直方图对比的实现代码如下所示. # -*- coding: utf-8 -*- # By:Eastmount import cv2 import numpy as np import matplotlib.pyplot as

  • react性能优化useMemo与useCallback使用对比详解

    目录 引言 对比 useMemo useCallback 引言 在介绍一下这两个hooks的作用之前,我们先来回顾一下react中的性能优化.在hooks诞生之前,如果组件包含内部state,我们都是基于class的形式来创建组件.当时我们也知道,react中,性能的优化点在于: 调用setState,就会触发组件的重新渲染,无论前后的state是否不同 父组件更新,子组件也会自动的更新 基于上面的两点,我们通常的解决方案是:使用immutable进行比较,在不相等的时候调用setState:在

  • 数据库连接池Druid与Hikari对比详解

    目录 Druid竞品对比 Hikari 官方性能测试数据 对比 总结 Druid竞品对比 功能类别 功能 Druid HikariCP DBCP Tomcat-jdbc C3P0 性能 PSCache 是 否 是 是 是 LRU 是 否 是 是 是 SLB负载均衡支持 是 否 否 否 否 稳定性 ExceptionSorter 是 否 否 否 否 扩展 扩展 Filter JdbcIntercepter 监控 监控方式 jmx/log/http jmx/metrics jmx jmx jmx 支

  • node.js使用express框架进行文件上传详解

    关于node.js使用express框架进行文件上传,主要来自于最近对Settings-Sync插件做的研究. 目前的研究算是取得的比较好的进展. Settings-Sync中通过快捷键上传文件,其实主要还是请求后端接口. 于是我便使用node.js模拟一个服务,这个服务其实就相当于github api(Settings-Sync实际请求的接口,比如token验证,gist存储创建等都是来自github 对应的api). 话不多说,直接代码贴起讲解: 1.创建一个node.js项目(这里我以ex

随机推荐