博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
实现自己的Koa2
阅读量:2240 次
发布时间:2019-05-09

本文共 7139 字,大约阅读时间需要 23 分钟。

这部分的代码在中demo文件夹中

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

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

1 const Koa = require('koa') 2 const app = new Koa() 3  4 app.use((ctx,next) => { 5   ctx.body = 'hello koa2' 6 }) 7  8 app.listen(3000, function () { 9   console.log('启动3000端口')10 })

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

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

APP  启动应用

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

1 const http = require('http')2 3 const server = http.createServer((req,res) => {4   res.writeHead('200')5   res.end('hello node')6 })7 server.listen(3000, function () {8   console.log('启动了3000端口')9 })

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

1 const http = require('http') 2  3 class application{ 4   constructor() { 5     this.callback = () => {} 6   } 7  8   use(callback) { 9     this.callback = callback10   }11 12   listen(...args) {13     const server = http.createServer((req,res) => {14       this.callback(req, res)15     })16     server.listen(...args)17   }18 }19 20 module.exports = application
1 const Koa3 = require('./index3') 2 const app = new Koa3() 3  4 app.use((req,res) => { 5   res.writeHead(200) 6   res.end('hello Koa3') 7 }) 8  9 app.listen(3003, function () {10   console.log('启动3003端口')11 })

例子4:

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

js的get和set方法

1 const yese = { 2   _name: '夜色', 3   get name() { 4     return this._name 5   }, 6   set name(val) { 7     console.log('new name is' + val) 8     this._name = val 9   }10 }11 12 console.log(yese.name)13 yese.name = '荷塘月色'14 console.log(yese.name)

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

     index7.js

1 const http = require('http') 2  3 //req是http模块里的 4 let request = { 5   get url () { 6     return this.req.url 7   } 8 } 9 10 let response = {11   get body () {12     return this._body13   },14   set body (val) {15     this._body = val16   }17 }18 19 // 把上面定义的request和response挂载到context对象中20 let context = {21    get url () {22      return this.request.url23    },24    get body () {25      return this.response.body26    },27   set body (val) {28      this.response.body = val29   }30 }31 32 33 class application{34   constructor() {35     // 把上面定义的context,request,response挂载到application中36     this.context = context37     this.request = request38     this.response = response39   }40 41   use(callback) {42     this.callback = callback43   }44   listen(...args) {45     const server = http.createServer(async (req, res) => {46       let ctx = this.createCtx(req,res)47       await this.callback(ctx)48       ctx.res.end(ctx.body)49     })50     server.listen(...args)51   }52   createCtx (req, res) {53     let ctx = Object.create(this.context)54     ctx.request = Object.create(this.request)55     ctx.response = Object.create(this.response)56     // 把http里的req赋值给ctx.request的req和ctx.req上57     ctx.req = ctx.request.req = req58     ctx.res = ctx.response.req = res59     return ctx60   }61 }62 63 module.exports = application

调用

1 const Koa3 = require('./index7') 2 const app = new Koa3() 3  4 app.use(async (ctx) => { 5   ctx.body = 'hello Koa2 '+ ctx.url 6 }) 7  8 app.listen(3003, function () { 9   console.log('启动3003端口')10 })

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

1 function add(x, y) { 2   return x + y 3 } 4 function double(z) { 5   return z*2 6 } 7  8 const middlewares = [add, double] 9 let len = middlewares.length10 // 中间件11 function compose(midds) {12   console.log('midds:'+midds)13    return (...args) => {14     console.log(...args)15      // 初始值16      let res = midds[0](...args)17      console.log(res)18      for (let i = 1; i < len; i++) {19        res = midds[i](res)20      }21      return res22    }23 }24 const fn = compose(middlewares)25 const res = fn(1,2)26 console.log(res)

 例子6、

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

1 async function fn1(next) { 2   console.log('fn1') 3   await next() 4   console.log('end fn1') 5 } 6 async function fn2(next) { 7   console.log('fn2') 8   await delay() 9   await next()10   console.log('end fn2')11 }12 function fn3() {13   console.log('fn3')14 }15 16 function delay() {17   return new Promise((resolve, reject) => {18     setTimeout(() => {19       resolve()20     }, 2000)21   })22 }23 24 function compose (middlewares) {25   return function () {26     return dispatch(0)27     28     function dispatch(i) {29       let fn = middlewares[i]30       if(!fn) {31         return Promise.resolve()32       }33       // 这俩行是compose的核心代码34       return Promise.resolve(fn(function next() {35         return dispatch(i+1)36       }))37     }38   }39   40 }41 42 const middlewares = [fn1, fn2, fn3]43 44 const finalfn = compose(middlewares)45 finalfn()

运行结果为:

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

 

index11.js

1 const http = require('http') 2  3 //req是http模块里的 4 let request = { 5   get url () { 6     return this.req.url 7   } 8 } 9 10 let response = {11   get body () {12     return this._body13   },14   set body (val) {15     this._body = val16   }17 }18 19 // 把上面定义的request和response挂载到context对象中20 let context = {21   get url () {22     return this.request.url23   },24   get body () {25     return this.response.body26   },27   set body (val) {28     this.response.body = val29   }30 }31 32 33 class application{34   constructor() {35     // 把上面定义的context,request,response挂载到application中36     this.context = context37     this.request = request38     this.response = response39     this.middlewares = []40   }41 42   use(callback) {43     this.middlewares.push(callback)44     // this.callback = callback45   }46   compose (middlewares) {47     return function (context) {48       return dispatch(0)49 50         function dispatch(i) {51           let fn = middlewares[i]52           if(!fn) {53             return Promise.resolve()54           }55           // 这俩行是compose的核心代码56           return Promise.resolve(fn(context, function next() {57             return dispatch(i+1)58           }))59         }60     }61   }62   listen(...args) {63     const server = http.createServer(async (req, res) => {64       let ctx = this.createCtx(req,res)65       const fn = this.compose(this.middlewares)66       await fn(ctx)67       ctx.res.end(ctx.body)68     })69     server.listen(...args)70   }71   createCtx (req, res) {72     let ctx = Object.create(this.context)73     ctx.request = Object.create(this.request)74     ctx.response = Object.create(this.response)75     // 把http里的req赋值给ctx.request的req和ctx.req上76     ctx.req = ctx.request.req = req77     ctx.res = ctx.response.req = res78     return ctx79   }80 }81 82 module.exports = application
1 const Koa3 = require('./index11') 2 const app = new Koa3() 3  4 function delay() { 5   return new Promise((resolve, reject) => { 6     setTimeout(() => { 7       resolve() 8     }, 2000) 9   })10 }11 12 app.use(async (ctx, next) => {13   ctx.body = '1'14   await next()15   ctx.body += '2'16 })17 18 app.use(async (ctx, next) => {19   ctx.body += '3'20   await delay()21   await next()22   ctx.body += '4'23 })24 25 app.use(async (ctx, next) => {26   ctx.body += '5'27 })28 29 app.listen(3003, function () {30   console.log('启动3003端口')31 })

运行结果: 

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

 

 

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

转载于:https://www.cnblogs.com/zhaobao1830/p/9333524.html

你可能感兴趣的文章
Go语言学习Part2:流程控制语句:for、if、else、switch 和 defer
查看>>
Go语言学习Part3:struct、slice和映射
查看>>
Go语言学习Part4-1:方法和接口
查看>>
Leetcode Go 《精选TOP面试题》20200628 69.x的平方根
查看>>
leetcode 130. Surrounded Regions
查看>>
【Python】详解Python多线程Selenium跨浏览器测试
查看>>
Jmeter之参数化
查看>>
Shell 和Python的区别。
查看>>
【JMeter】1.9上考试jmeter测试调试
查看>>
【虫师】【selenium】参数化
查看>>
【Python练习】文件引用用户名密码登录系统
查看>>
学习网站汇总
查看>>
【Loadrunner】性能测试报告实战
查看>>
【自动化测试】自动化测试需要了解的的一些事情。
查看>>
【selenium】selenium ide的安装过程
查看>>
【手机自动化测试】monkey测试
查看>>
【英语】软件开发常用英语词汇
查看>>
Fiddler 抓包工具总结
查看>>
【雅思】雅思需要购买和准备的学习资料
查看>>
【雅思】雅思写作作业(1)
查看>>