Я пишу класс обработчика событий для приложения обмена сообщениями, и у меня есть некоторый код, который выглядит примерно так:
class EventHandler {
constructor(client, chatroomManager) {
this.client = client;
this.chatroomManager = chatroomManager;
}
handleJoin(roomId, cb) {
...
}
handleLeave(roomId, cb) {
if (!this.client.isLoggedIn()) {
cb("err");
return;
}
const chatroom = this.chatroomManager.getRoomById(roomId);
// check that chatroom exists
if (chatroom != null) {
// check that user was already in the room
if (chatroom.getRoomId() in this.client.rooms) {
chatroom.removeUser(this.client);
} else {
cb("error")
}
} else {
cb("error");
}
}
handleMessage(roomId, message, cb) {
if (!this.client.isLoggedIn()) {
cb("err");
return;
}
const chatroom = this.chatroomManager.getRoomById(roomId);
// check that chatroom exists
if (chatroom != null) {
// check that user was already in the room
if (chatroom.getRoomId() in this.client.rooms) {
chatroom.addEntry(this.client.username, message);
} else {
cb("error")
}
} else {
cb("error");
}
}
}
Как видите, в * много повторяющегося кода 1004 * и handleMessage
методы (и даже больше методов в полном коде). Я хочу избавиться от этого как можно больше.
Прежде всего, я ожидаю, что смогу заменить первый оператор if
декоратором ES7, например:
class EventHandler {
...
@requirelogin
handleLeave(roomId, cb) {
const chatroom = this.chatroomManager.getRoomById(roomId);
// check that chatroom exists
if (chatroom != null) {
// check that user was already in the room
if (chatroom.getRoomId() in this.client.rooms) {
chatroom.removeUser(this.client);
} else {
cb("error")
}
} else {
cb("error");
}
}
}
Во-вторых, я думаю, что если я смогу провести рефакторинг метода chatroomManager.getRoomById
для возврата Promise, то я могу определить вспомогательную функцию:
validateRoom(roomId) {
return chatroomManager.getRoomById(roomId).then(room => {
if (roomId in this.client.rooms) {
return room;
} else {
throw new Error("Client is not in room");
}
}
}
Затем я могу рефакторинг следующим образом:
class EventHandler {
...
@requirelogin
handleLeave(roomId, cb) {
this.validateRoom(roomId)
.then(room => room.removeUser(this.client))
.catch(cb);
}
}
Я доволен этим, но мне интересно, можно ли это еще больше упростить? Кажется, что этот шаблон
this.validateRoom(roomId)
.then(room => { /* do something */ })
.catch(cb);
будет повторяться много раз, и мне интересно, есть ли чистый способ извлечь это (возможно, в качестве другого декоратора, хотя я не вижу, как)? В идеале я хотел бы иметь установку, где API c publi EventHandler
остается таким же
handleLeave(roomId, cb)
handleMessage(roomId, message, cb)
, но под капотом я реализую что-то вроде
handleLeave(room) {
room.removeUser(this.client);
}
handleMessage(room, message) {
room.addEntry(this.client.username, message);
}
Is Есть ли способ сделать это 1031 *? Должен ли я сделать какой-либо большой рефакторинг для кода, чтобы сделать это?