如何使用中间件优化多对多通信?
背景介绍
这是设计模式系列的第九节,学习的是patterns.dev里设计模式中中间件模式内容,由于是资料是英文版,所以我的学习笔记就带有翻译的性质,但并不是翻译,记录的是自己的学习过程和理解。
第二节:JS和迪丽热巴一样有专业替身?没听过的快来补补课...
第三节:还在层层传递props?来学学非常实用的供应商模式吧
第四节:都知道JavaScript原型,但设计模式里的原型模式你会用吗?
第五节:React Hooks时代,怎么实现视图与逻辑分离呢?
第八节:在React Hook时代,Object.assign这种混合写法还要用吗?
写在前面
对于中间件的概念相信大家都不会太陌生,就类似生活中的中介一样。具体做法就是在两个组件中间通过中间件,完成两个组件之间的通信,而不直接通信。
极简释义———中间件模式
使用中间件在多个组件之间的通信;
开始学习
中间件模式允许不同组件之间通过一个控制中心进行交互,这个控制中心通常称为中间件。中间件接受请求,然后转发出去。在JavaScript中,中间件通常以一个Object或者function的形式展现出来。
可以把这种模式比作飞机场里空中交通管控中心和飞行员的关系;不同飞行员之间也不直接交流,而是飞行员联系控制中心,再由控制中心通知其他相关飞行员,以免飞机之间发生碰撞事故;
在Javascript中,通常我们要处理多对多模型的数据,当组件很多的时候,组件之间的通信就会变得复杂而混乱。
正如上图显示,当组件很多时,并且互相之间有复杂通信需求时,使用一个统一的中间件来简化这种复杂多对多通信场景。
经典案例
Chartroom
一个中间件经典的使用案例分析是聊天室,聊天室里的用户并不是直接通话,而是通过聊天室服务器进行通话:
class ChatRoom {
logMessage(user, message) {
const sender = user.getName();
console.log(`${new Date().toLocaleString()} [${sender}]: ${message}`);
}
}
class User {
constructor(name, chatroom) {
this.name = name;
this.chatroom = chatroom;
}
getName() {
return this.name;
}
send(message) {
this.chatroom.logMessage(this, message);
}
}
const chatroom = new ChatRoom();
const user1 = new User("John Doe", chatroom);
const user2 = new User("Jane Doe", chatroom);
user1.send("Hi there!");
user2.send("Hey!");
我们通过new一个User对象来连接用户和聊天室,通过用户发送聊天信息,交由ChartRoom然后统一处理。
Express.js
Express是一个流行的服务器框架,相信大家都有所接触。我们可以给特定的路径添加回调函数。
比如说有这样一个场景,我们要给一个根路径添加一个回调函数,在回调函数中设置请求头。
const app = require("express")();
app.use("/", (req, res, next) => {
req.headers["test-header"] = 1234;
next();
});
我们通过中间件回调函数修改请求头,next方法调用请求响应周期的下一次回调函数;我们可以在请求和响应之间建立一个有效的中间件函数链;

此时我们可以通过添加另一个中间件函数来确认一下新加的header字段是否成功;前一次中间件函数的修改会沿着函数链传递。
const app = require("express")();
app.use("/", (req, res, next) => {
req.headers["test-header"] = 1234;
next();
}, (req, res, next) => {
console.log(`Request has test header: ${!!req.headers["test-header"]}`);
next();
});
因此我们可以通过一个或多个中间件函数修改请求Object,直到响应。
const app = require("express")();
const html = require("./data");
app.use(
"/",
(req, res, next) => {
req.headers["test-header"] = 1234;
next();
},
(req, res, next) => {
console.log(`Request has test header: ${!!req.headers["test-header"]}`);
next();
}
);
app.get("/", (req, res) => {
res.set("Content-Type", "text/html");
res.send(Buffer.from(html));
});
app.listen(8080, function() {
console.log("Server is running on 8080");
});
每当用户访问根路径'/'时,两个回调函数都会被调用;
中间件模式让所有通信都通过一个控制中心,从而简化组件之间的多对多场景交互。
转载自:https://juejin.cn/post/7198782832177692727