Skip to content

Mediator/Middleware Pattern

The mediator pattern makes it possible for components to interact with each other through a central point: the mediator. Instead of directly talking to each other, the mediator receives the requests, and sends them forward! In JavaScript, the mediator is often nothing more than an object literal or a function.

You can compare this pattern to the relationship between an air traffic controller and a pilot. Instead of having the pilots talk to each other directly, which would probably end up being quite chaotic, the pilots talk the air traffic controller. The air traffic controller makes sure that all planes receive the information they need in order to fly safely, without hitting the other airplanes.

Although we’re hopefully not controlling airplanes in JavaScript, we often have to deal with multidirectional data between objects. The communication between the components can get rather confusing if there is a large number of components.

alt text

Instead of letting every objects talk directly to the other objects, resulting in a many-to-many relationship, the object’s requests get handled by the mediator. The mediator processes this request, and sends it forward to where it needs to be.

alt text

A good use case for the mediator pattern is a chatroom! The users within the chatroom won’t talk to each other directly. Instead, the chatroom serves as the mediator between the users.

class ChatRoom { logMessage(user, message) { const time = new Date(); const sender = user.getName();

console.log(`${time} [${sender}]: ${message}`);

} }

class User { constructor(name, chatroom) { this.name = name; this.chatroom = chatroom; }

getName() { return this.name; }

send(message) { this.chatroom.logMessage(this, message); } } We can create new users that are connected to the chat room. Each user instance has a send method which we can use in order to send messages.

在演练场中查看代码

Case Study

Express.js is a popular web application server framework. We can add callbacks to certain routes that the user can access.

Say we want add a header to the request if the user hits the root '/'. We can add this header in a middleware callback.

js
const app = require("express")();

app.use("/", (req, res, next) => {
  req.headers["test-header"] = 1234;
  next();
});

The next method calls the next callback in the request-response cycle. We’d effectively be creating a chain of middleware functions that sit between the request and the response, or vice versa.

alt text

Let’s add another middleware function that checks whether the test-header was added correctly. The change added by the previous middleware function will be visible throughout the chain.

js
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();
  }
);

Perfect! We can track and modify the request object all the way to the response through one or multiple middleware functions.

在演练场中查看代码

Every time the user hits a root endpoint '/', the two middleware callbacks will be invoked.

The middleware pattern makes it easy for us to simplify many-to-many relationships between objects, by letting all communication flow through one central point.

References

最后更新于:

评论区
评论区空空如也
发送评论
名字
0 / 20
邮箱
0 / 100
评论内容
0 / 140
由于是非实名评论,所以不提供删除功能。如果你需要删除你发送的评论,或者是其他人的评论对你造成了困扰,请 发邮件给我 。同时评论区会使用 AI + 人工的方式进行审核,以达到合规要求。