这部分的代码在https://github.com/zhaobao1830/koa2中demo文件夹中

Koa就是基于node自带的http模块,经过封装,监听端口,实现ctx(上下文)管理,中间件管理等

例子1、koa监听3000端口,在页面输出值

 const Koa = require('koa')
const app = new Koa() app.use((ctx,next) => {
ctx.body = 'hello koa2'
}) app.listen(, function () {
console.log('启动3000端口')
})

ctx 是封装了request和response的上下文

next  的作用就是执行下一个中间件

APP  启动应用

例子2、http监听3000端口,页面返回值

 const http = require('http')

 const server = http.createServer((req,res) => {
res.writeHead('')
res.end('hello node')
})
server.listen(, function () {
console.log('启动了3000端口')
})

例子3、使用http封装一个简单的web服务

 const http = require('http')

 class application{
constructor() {
this.callback = () => {}
} use(callback) {
this.callback = callback
} listen(...args) {
const server = http.createServer((req,res) => {
this.callback(req, res)
})
server.listen(...args)
}
} module.exports = application
 const Koa3 = require('./index3')
const app = new Koa3() app.use((req,res) => {
res.writeHead()
res.end('hello Koa3')
}) app.listen(, function () {
console.log('启动3003端口')
})

例子4:

koa2中的ctx就是上下文,用来挂载request和response对象

js的get和set方法

 const yese = {
_name: '夜色',
get name() {
return this._name
},
set name(val) {
console.log('new name is' + val)
this._name = val
}
} console.log(yese.name)
yese.name = '荷塘月色'
console.log(yese.name)

加入ctx上下文,封装了http里的request和response

index7.js

 const http = require('http')

 //req是http模块里的
let request = {
get url () {
return this.req.url
}
} let response = {
get body () {
return this._body
},
set body (val) {
this._body = val
}
} // 把上面定义的request和response挂载到context对象中
let context = {
get url () {
return this.request.url
},
get body () {
return this.response.body
},
set body (val) {
this.response.body = val
}
} class application{
constructor() {
// 把上面定义的context,request,response挂载到application中
this.context = context
this.request = request
this.response = response
} use(callback) {
this.callback = callback
}
listen(...args) {
const server = http.createServer(async (req, res) => {
let ctx = this.createCtx(req,res)
await this.callback(ctx)
ctx.res.end(ctx.body)
})
server.listen(...args)
}
createCtx (req, res) {
let ctx = Object.create(this.context)
ctx.request = Object.create(this.request)
ctx.response = Object.create(this.response)
// 把http里的req赋值给ctx.request的req和ctx.req上
ctx.req = ctx.request.req = req
ctx.res = ctx.response.req = res
return ctx
}
} module.exports = application

调用

 const Koa3 = require('./index7')
const app = new Koa3() app.use(async (ctx) => {
ctx.body = 'hello Koa2 '+ ctx.url
}) app.listen(, function () {
console.log('启动3003端口')
})

例子5、(这个例子是同步的)compose中间件

 function add(x, y) {
return x + y
}
function double(z) {
return z*
} const middlewares = [add, double]
let len = middlewares.length
// 中间件
function compose(midds) {
console.log('midds:'+midds)
return (...args) => {
console.log(...args)
// 初始值
let res = midds[](...args)
console.log(res)
for (let i = ; i < len; i++) {
res = midds[i](res)
}
return res
}
}
const fn = compose(middlewares)
const res = fn(,)
console.log(res)

例子6、

自己实现的一个简单的compose代码

 async function fn1(next) {
console.log('fn1')
await next()
console.log('end fn1')
}
async function fn2(next) {
console.log('fn2')
await delay()
await next()
console.log('end fn2')
}
function fn3() {
console.log('fn3')
} function delay() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, )
})
} function compose (middlewares) {
return function () {
return dispatch() function dispatch(i) {
let fn = middlewares[i]
if(!fn) {
return Promise.resolve()
}
// 这俩行是compose的核心代码
return Promise.resolve(fn(function next() {
return dispatch(i+)
}))
}
} } const middlewares = [fn1, fn2, fn3] const finalfn = compose(middlewares)
finalfn()

运行结果为:

个人理解:核心就是先执行方法里的值,遇到了next(),就执行下一层的(koa2是一个类似洋葱圈的结构)

index11.js

 const http = require('http')

 //req是http模块里的
let request = {
get url () {
return this.req.url
}
} let response = {
get body () {
return this._body
},
set body (val) {
this._body = val
}
} // 把上面定义的request和response挂载到context对象中
let context = {
get url () {
return this.request.url
},
get body () {
return this.response.body
},
set body (val) {
this.response.body = val
}
} class application{
constructor() {
// 把上面定义的context,request,response挂载到application中
this.context = context
this.request = request
this.response = response
this.middlewares = []
} use(callback) {
this.middlewares.push(callback)
// this.callback = callback
}
compose (middlewares) {
return function (context) {
return dispatch() function dispatch(i) {
let fn = middlewares[i]
if(!fn) {
return Promise.resolve()
}
// 这俩行是compose的核心代码
return Promise.resolve(fn(context, function next() {
return dispatch(i+)
}))
}
}
}
listen(...args) {
const server = http.createServer(async (req, res) => {
let ctx = this.createCtx(req,res)
const fn = this.compose(this.middlewares)
await fn(ctx)
ctx.res.end(ctx.body)
})
server.listen(...args)
}
createCtx (req, res) {
let ctx = Object.create(this.context)
ctx.request = Object.create(this.request)
ctx.response = Object.create(this.response)
// 把http里的req赋值给ctx.request的req和ctx.req上
ctx.req = ctx.request.req = req
ctx.res = ctx.response.req = res
return ctx
}
} module.exports = application
 const Koa3 = require('./index11')
const app = new Koa3() function delay() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, )
})
} app.use(async (ctx, next) => {
ctx.body = ''
await next()
ctx.body += ''
}) app.use(async (ctx, next) => {
ctx.body += ''
await delay()
await next()
ctx.body += ''
}) app.use(async (ctx, next) => {
ctx.body += ''
}) app.listen(, function () {
console.log('启动3003端口')
})

运行结果:

打开页面 2秒以后出现:13542 (async await要等异步的操作都执行完,才会输出结果)

Koa2的其他知识

app.use()就算是一个中间件
中间件概念:一个http请求是:发起请求request,返回结果response,中间的部分就可以理解为中间件

实现自己的Koa2的更多相关文章

  1. Koa2 的安装运行记录(二)

    参考 :koa2-boilerplate    https://github.com/superalsrk/koa2-boilerplate Ajax Login and Ajax Logout in ...

  2. Koa2 的安装运行记录(一)

    1.参考koa+react(一) http://blog.suzper.com/2016/10/19/koa-react-%E4%B8%80/ 为了使用 KOA2 能够运行,必须能够使用ES7语法 a ...

  3. koa2+koa-views示例

    app.js var Koa = require('koa') var fs = require('fs') var path = require('path') var koaStaticPlus ...

  4. Koa2 源码解析(1)

    Koa2 源码解析 其实本来不想写这个系列文章的,因为Koa本身很精简,一共就4个文件,千十来行代码. 但是因为想写 egg[1] 的源码解析,而egg是基于Koa2的,所以就先写个Koa2的吧,用作 ...

  5. nodejs6下使用koa2

    koa2里面使用ES7的语法,如async.await所以需要运行在node7.6之后:但在node7.6之前也可以利用babel是的koa2可以运行. 首先项目中安装babel,和babel的几个模 ...

  6. koa2 use里面的next到底是什么

    koa2短小精悍,女人不爱男人爱. 之前一只有用koa写一点小程序,自认为还吼吼哈,知道有一天某人问我,你说一下 koa或者express中间件的实现原理.然后我就支支吾吾,好久吃饭都不香. 那么了解 ...

  7. koa2 controller中实现类似sleep的延迟功能

    今天有同事问我如何在koa2中的controller中使用延迟执行的功能,他直接在controller中使用setTimeout,但是没效果. 错误的代码类似下面这样: // 错误的方法 export ...

  8. 使用下一代web开发框架koa2搭建自己的轻服务器

    Koa 是由 Express 原班人马亲情打造的新一代web框架.既然已经有 Express 了,为什么又要搞一个Koa出来呢?因为 Koa 相比 Express 体积更小,代码更健壮,作用更纯粹. ...

  9. 一键生成koa/koa2项目:

    一键生成koa/koa2项目: 1. npm install -g koa-generator 2.新建项目目录 koa mytest (koa1项目) koa2 koa2test (koa2项目) ...

  10. Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例

    目录 前言 搭建项目及其它准备工作 创建数据库 创建Koa2项目 安装项目其它需要包 清除冗余文件并重新规划项目目录 配置文件 规划示例路由,并新建相关文件 实现数据访问和业务逻辑相关方法 编写mys ...

随机推荐

  1. webstorm的一些小技巧

    1.怎样禁止自动保存文件: 设置--->外观和行为--->常规--->Synchronization--->要么四个全不选,要么把最后两个不选 Settings--->A ...

  2. JVM调优命令-jstack

    jstack jstack用于生成java虚拟机当前时刻的线程快照.线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁 ...

  3. Hive记录-Hive常用命令操作

    1.hive支持四种数据模型 • external table ---外部表:Hive中的外部表和表很类似,但是其数据不是放在自己表所属的目录中,而是存放到别处,这样的好处是如果你要删除这个外部表,该 ...

  4. Code::Blocks代码自动提示设置及常用快捷键

    Code::Blocks代码自动提示设置及常用快捷键(适用windows和linux) 1)以下需要设置的地方均在Settings->Editor...弹出的对话框中. 2)不少命令都可针对当前 ...

  5. Java编程思想 学习笔记9

    九.接口 接口和内部类为我们提供了一种将接口与实现分离的更加结构化的方法. 1.抽象类和抽象方法  抽象类是普通的类与接口之间的一种中庸之道.创建抽象类是希望通过这个通用接口操纵一系列类. Java提 ...

  6. Matplotlib中plt.rcParams用法(设置图像细节)

    import numpy as np import matplotlib.pyplot as plt from matplotlib.colors import ListedColormap %mat ...

  7. jQuery基础 (一)——样式篇(认识jQuery)

    一.认识 //等待dom元素加载完毕. $(document).ready(function(){ alert("Hello World!"); }); 二.jQuery对象与DO ...

  8. webkitAnimationEnd事件与webkitTransitionEnd事件

    写一个焦点图demo,css3动画完成以后要把它隐藏掉,这里会用到css3的事件,以前没有接触过,结果查了一下发现这是一片新天地啊,而且里面还有好多坑,比如重复动画多次触发什么的.anyway,我还是 ...

  9. PhoneUtil

    package cn.fraudmetrix.octopus.horai.biz.utils; import org.springframework.util.StringUtils; import ...

  10. [CQOI2012]组装 (贪心)

    CQOI2012]组装 solution: 蒟蒻表示并不会模拟退火,所以用了差分数组加贪心吗.我们先来看题: 在数轴上的某个位置修建一个组装车间 到组装车间距离的平方的最小值. 1<=n< ...