内容简介:首先我们先简单封装一个模块 Application 保证服务的正常运行;首先我们假设我们的 context 是这么一个数据结构:改写 Application
首先我们先简单封装一个模块 Application 保证服务的正常运行;
- 初始化一个项目
$ npm init -y ... 复制代码
- 创建文件 application.js 并并编写如下代码;
const http = require('http'); class Application{ // 初始化 constructor(){ this.callback = () => {} } // 设置回调函数 use(callback){ this.callback = callback; } // listen 创建服务并对服务进行监听 listen(...args){ const server = http.createServer((req, res) => { this.callback(req, res); }); server.listen(...args); } } module.exports = Application; 复制代码
- 创建 server.js 文件,调用 Application 模块起一个服务:
const Application = require('./application.js'); const app = new Application(); app.use((req, res) => { res.writeHead(200); res.end('hello world'); }); app.listen(3000, () => { console.log('监听端口:3000'); }); 复制代码
二、 Application 模块挂载 context
首先我们假设我们的 context 是这么一个数据结构:
- context 中挂载了 request response req res, 同时还有抽离的额外属性 url body
- request 中挂载了 req, 同时还有抽离的额外属性 url
- response 中挂载了 res, 同时还有抽离的额外属性 body
context: { url: String, body: String, request: { url: String, req: Object }, response: { body: String, res: Object }, req: Object, res: Object } 复制代码
改写 Application
- 设计 context request response 原型数据结构;
- 将 context request response 原型数据结构挂载到 Application
- 编写函数创建 context
- 改写回调函数的调用方式;
const http = require('http'); // [1]构建数据结构(作为原型使用) const request = { // 因为后期 request 将会挂载上 req 所以存在 this.req get url(){ return this.req.url; } }; const response = { get body(){ return this._body; }, set body(val){ this._body = val; } }; const context = { // 因为后期 context 将会挂载上 request response 所以存在 this.request 和 this.response get url(){ return this.request.url; }, get body(){ return this.response.body; }, set body(val){ this.response.body = val; } } class Application{ constructor(){ this.callback = () => {}, // [2]将原型挂载到 Application this.context = context; this.request = request; this.response = response; } use(callback){ this.callback = callback; } // [3]创建 context 函数,挂载上 request response req res createCtx(req, res){ const ctx = Object.create(this.context); ctx.request = Object.create(this.request); ctx.response = Object.create(this.response); ctx.req = ctx.request = req; ctx.res = ctx.response = res; return ctx; } listen(...args){ const server = http.createServer((req, res) => { // [4]创建 context, 并进行简单修改 const ctx = this.createCtx(req, res); this.callback(ctx); ctx.res.end(ctx.body); }); server.listen(...args); } } module.exports = Application; 复制代码
修改 server.js 中 Application 的引用
const Application = require('./application.js'); const app = new Application(); app.use( ctx => { ctx.body = 'hello world' }); app.listen(3000, () => { console.log('监听端口:3000'); }); 复制代码
三、 中间件的实现
3.1 洋葱模型实现
// 场景模拟 // 异步 promise 模拟 const delay = async () => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(); }, 2000); }); } // 中间间模拟 const fn1 = async (ctx, next) => { console.log(1); await next(); console.log(2); } const fn2 = async (ctx, next) => { console.log(3); await delay(); await next(); console.log(4); } const fn3 = async (ctx, next) => { console.log(5); } const middlewares = [fn1, fn2, fn3]; // compose 实现洋葱模型 const compose = (middlewares, ctx) => { const dispatch = (i) => { let fn = middlewares[i]; if(!fn){ return Promise.resolve() } return Promise.resolve(fn(ctx, () => { return dispatch(i+1); })); } return dispatch(0); } compose(middlewares, 1); 复制代码
3.2 compose 函数在 Application 模块中的使用:
const http = require('http'); const request = { get url(){ return this.req.url; } }; const response = { get body(){ return this._body; }, set body(val){ this._body = val; } }; const context = { get url(){ return this.request.url; }, get body(){ return this.response.body; }, set body(val){ this.response.body = val; } } class Application{ constructor(){ this.context = context; this.request = request; this.response = response; // 初始化中间件数组 this.middlewares = []; } // 通过push的方式进行添加中间件 use(middleware){ this.middlewares.push(middleware); } createCtx(req, res){ const ctx = Object.create(this.context); ctx.request = Object.create(this.request); ctx.response = Object.create(this.response); ctx.req = ctx.request = req; ctx.res = ctx.response = res; return ctx; } // compose 函数 compose(middlewares, ctx){ const dispatch = (i) => { const fn = middlewares[i]; if(!fn){ return Promise.resolve(); }else{ return Promise.resolve(fn(ctx, () => { dispatch(i +1 ); })); } } return dispatch(0); } listen(...args){ // 改用 async await 并调用compose const server = http.createServer(async (req, res) => { const ctx = this.createCtx(req, res); await this.compose(this.middlewares, ctx); ctx.res.end(ctx.body); }); server.listen(...args); } } module.exports = Application; 复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 使用四十行代码实现一个精简版 koa
- 遵守 TDD 实现一个精简版的 HashMap
- 实现Pormise,超级精简,一看就能明白Promise的运行原理
- Vuex和Redux都使用的Flux设计模式精简版实现
- 如何精简一本书
- 设计模式精简图册
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Shallows
Nicholas Carr / W. W. Norton & Company / 2011-6-6 / USD 15.95
"Is Google making us stupid?" When Nicholas Carr posed that question, in a celebrated Atlantic Monthly cover story, he tapped into a well of anxiety about how the Internet is changing us. He also crys......一起来看看 《The Shallows》 这本书的介绍吧!