на клиенте у меня есть класс для работы с Websocket:
class WebsocketsWork {
constructor(headers) {
this._allowedTypes = data.requests;
this.ws = new WebSocket("ws://localhost:3050", headers);
}
_waitForConnection(callback, interval) {
if (this.ws.readyState === 1) {
callback();
} else {
const that = this;
// optional: implement backoff for interval here
setTimeout(function () {
that._waitForConnection(callback, interval);
}, interval);
}
}
/**
* Отправка сообщения на сервер
* @param {string} type Тип отправки
* @param {obj} payload Данные для отправки
* @public
*/
sendPayload(type, payload, callback) {
if (!Object.values(this._allowedTypes).includes(type)) {
throw new Error(`Такого типа для отправки не существует: ${type}`);
}
this._waitForConnection(() => {
const obj = { type, payload };
this.ws.send(JSON.stringify(obj));
if (typeof callback !== "undefined") {
callback();
}
}, 1000);
}
/**
* Соединение с сервером установлено
* @param {function} callback Функция, которая будет выполняться при соединении
* @public
*/
open(callback) {
this.ws.addEventListener("open", (event) => { callback(event); });
}
/**
* Соединение с сервером закрыто
* @public
*/
close(callback) {
this.ws.addEventListener("close", (event) => { callback(event); });
}
/**
* Соединение с сервером прервано ошибкой
* @param {function} callback Функция, которая будет выполняться при появлении ошибки
* @public
*/
error(callback) {
this.ws.addEventListener("error", (event) => { callback(event); });
}
/**
* Получение ответа от сервера
* @param {function} callback Функция, которая будет выполняться при получении ответа
* @public
*/
getAnswer(callback = function (data) { console.log(JSON.parse(data)); }) {
this.ws.addEventListener("message", ({ data }) => {
// Получение текущего типа отправки сообщения
const { currentType, error, data: dataFromParse } = JSON.parse(data);
if (error) {
callback(error, null);
return;
}
callback(null, { currentType, ...dataFromParse });
});
}
}
export default WebsocketsWork;
также есть отдельный объект с методами для отправки данных:
const permissions = {
url : "http://localhost:3050/api/permission",
websocket: {
ws: new WebsocketsWork(["access_token", cookie.get("token")])
}
};
// Открываем соединение
permissions.websocket.ws.open(() => console.log("connected"));
/**
* Добавление разрешения через websocket
* @param {Object} payload Объект с данными
* @param {Function} callback Функция обратного вызова для получения ответа
*/
permissions.websocket.add = function(payload, callback) {
this.ws.sendPayload(data.requests.PERMISSIONS_ADD, payload, () => {
this.ws.getAnswer((error, res) => {
if (res.currentType !== data.requests.PERMISSIONS_ADD) {
return callback(null, null);
}
callback(error, res);
});
});
}
/**
* Получение разрешений через websocket
* @param {Object} payload Объект с данными
* @param {Function} callback Функция обратного вызова для получения ответа
*/
permissions.websocket.getAll = function(payload, callback) {
this.ws.sendPayload(data.requests.PERMISSIONS_GET_ALL, payload, () => {
this.ws.getAnswer((error, res) => {
if (res.currentType !== data.requests.PERMISSIONS_GET_ALL) {
return callback(null, null);
}
callback(error, res);
});
});
}
я импортирую этот файл на страницу с кнопкой отправления и применяю метод add:
import permissions from "../permissions.js";
btn.addEventListener("click", () => {
permissions.websocket.add(payload, (error, result) => {
if (result === null) return;
if (error) {
alert.error(error);
loader.hide();
console.error(error);
return;
}
const { success, errors, message, error: serverError, permission } = result;
...
});
на стороне сервера вызываю контроллер в главном index.js файле:
const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
// Обработка websocket соединений
new PermissionsControllerWebsocket(wss);
вот так выглядит PermissionsControllerWebsocket:
class PermissionControllerWebsocket {
constructor(wss) {
this.wss = wss;
this.initialize();
}
initialize() {
this.wss.on("connection", (ws, req) => {
try {
console.log("new connection");
this.add(ws, req);
} catch(error) {
Logger.error(`PermissionsWebsocketController.initialize: ${error}`, 500);
}
});
}
add(ws, req) {
ws.on("message", async (message) => {
const data = JSON.parse(message);
if (data.type === "PERMISSIONS_ADD") {
// code...
const resultToSend = { currentType: "PERMISSIONS_ADD", payload };
ws.send(JSON.stringify(resultToSend)); // Отправляем информацию о том, что все добавилось
const resultToModerator = { currentType: "PERMISSIONS_GET_ALL", ...resultToSend };
this.wss.clients.forEach((client) => {
if (client !== ws && client.readyState === require("ws").OPEN) {
client.send(JSON.stringify(resultToModerator)); // Отправляем информацию отдельному клиенту, который постоянно ожидает новые данные (resultToSend)
}
});
}
});
}
}
на странице ожидания новых данных такая логика:
import permissions from "../permissions.js";
permissions.websocket.getAll({ l: 5, o: 0 }, (error, data) => {
if (data === null) return;
// code ...
});
прикол в том что я не получаю на странице ожидания PERMISSIONS_GET_ALL нужный тип с данными, мне приходит PERMISSIONS_ADD, почему так?