Javascript рефакторинг шаблона в декораторы для обработчика событий приложения чата - PullRequest
0 голосов
/ 12 апреля 2020

Я пишу класс обработчика событий для приложения обмена сообщениями, и у меня есть некоторый код, который выглядит примерно так:

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 *? Должен ли я сделать какой-либо большой рефакторинг для кода, чтобы сделать это?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...