← Назад к вопросам

Как происходит работа с вебсокетом на Frontend?

3.0 Senior🔥 131 комментариев
#REST API и HTTP#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Работа с WebSocket на Frontend

WebSocket — это протокол для двусторонней коммуникации между клиентом и сервером. На Frontend используется встроенный API для создания и управления WebSocket соединениями.

Базовое подключение

const socket = new WebSocket("ws://localhost:8000/ws");

socket.addEventListener("open", () => {
    console.log("Соединение установлено");
    socket.send("Hello Server!");
});

socket.addEventListener("message", (event) => {
    console.log("Сообщение от сервера:", event.data);
});

socket.addEventListener("error", (event) => {
    console.error("Ошибка WebSocket:", event);
});

socket.addEventListener("close", () => {
    console.log("Соединение закрыто");
});

Состояния WebSocket

console.log(socket.readyState);
// WebSocket.CONNECTING = 0
// WebSocket.OPEN = 1
// WebSocket.CLOSING = 2
// WebSocket.CLOSED = 3

if (socket.readyState === WebSocket.OPEN) {
    socket.send("Message");
}

Отправка и получение JSON

const message = {
    type: "chat_message",
    content: "Hello everyone!",
    timestamp: new Date().toISOString()
};

socket.send(JSON.stringify(message));

socket.addEventListener("message", (event) => {
    try {
        const data = JSON.parse(event.data);
        if (data.type === "chat_message") {
            displayMessage(data.content);
        }
    } catch (error) {
        console.error("Ошибка парсинга JSON:", error);
    }
});

Переподключение при разрыве связи

class WebSocketManager {
    constructor(url, maxRetries = 5) {
        this.url = url;
        this.socket = null;
        this.maxRetries = maxRetries;
        this.retries = 0;
        this.messageQueue = [];
        this.connect();
    }
    
    connect() {
        this.socket = new WebSocket(this.url);
        
        this.socket.addEventListener("open", () => {
            console.log("WebSocket подключён");
            this.retries = 0;
            this.flushQueue();
        });
        
        this.socket.addEventListener("message", (event) => {
            this.handleMessage(event.data);
        });
        
        this.socket.addEventListener("close", () => {
            this.reconnect();
        });
    }
    
    reconnect() {
        if (this.retries < this.maxRetries) {
            const delay = Math.pow(2, this.retries) * 1000;
            console.log("Переподключение через", delay, "ms");
            setTimeout(() => {
                this.retries++;
                this.connect();
            }, delay);
        }
    }
    
    send(message) {
        if (this.socket && this.socket.readyState === WebSocket.OPEN) {
            this.socket.send(JSON.stringify(message));
        } else {
            this.messageQueue.push(message);
        }
    }
    
    flushQueue() {
        while (this.messageQueue.length > 0) {
            const message = this.messageQueue.shift();
            this.socket.send(JSON.stringify(message));
        }
    }
    
    close() {
        if (this.socket) {
            this.socket.close();
        }
    }
}

const manager = new WebSocketManager("ws://localhost:8000/ws");
manager.send({ type: "ping" });

React компонент с WebSocket

import { useEffect, useState, useRef } from "react";

function ChatComponent() {
    const [messages, setMessages] = useState([]);
    const socketRef = useRef(null);
    
    useEffect(() => {
        socketRef.current = new WebSocket("ws://localhost:8000/chat");
        
        socketRef.current.onopen = () => {
            console.log("Подключено");
        };
        
        socketRef.current.onmessage = (event) => {
            const message = JSON.parse(event.data);
            setMessages((prev) => [...prev, message]);
        };
        
        return () => {
            if (socketRef.current) {
                socketRef.current.close();
            }
        };
    }, []);
    
    const sendMessage = (text) => {
        if (socketRef.current && socketRef.current.readyState === WebSocket.OPEN) {
            socketRef.current.send(JSON.stringify({ content: text }));
        }
    };
    
    return (
        <div>
            <div className="messages">
                {messages.map((msg, idx) => (
                    <div key={idx}>{msg.content}</div>
                ))}
            </div>
            <input type="text" placeholder="Сообщение..." />
        </div>
    );
}

export default ChatComponent;

Безопасность

const token = localStorage.getItem("auth_token");
const socket = new WebSocket("wss://api.example.com/ws?token=" + token);

socket.onmessage = (event) => {
    try {
        const data = JSON.parse(event.data);
        if (data.type && data.content) {
            processMessage(data);
        }
    } catch (error) {
        console.error("Невалидные данные:", error);
    }
};

Ключевые точки

  • Двусторонняя коммуникация — сервер может отправить данные в любой момент
  • Постоянное соединение — одно TCP соединение на весь сеанс
  • Низкая задержка — идеально для real-time приложений
  • Переподключение — реализуй exponential backoff при потере связи
  • Очередирование — сохраняй сообщения, если соединение не открыто
  • Очистка — закрывай соединение при размонтировании компонента
  • WSS в production — используй защищённое соединение всегда
Как происходит работа с вебсокетом на Frontend? | PrepBro