чорнетка сокети
Встановимо на бекенді
npm i socket.io
сокети працюють окремо від експрес. Підрефакторимо індекс фапйл
const socketIO = require("socket.io")
і треба підправити запуск сервера так, зоб підключити сокети до нашого сервера
// ===========SERVER INIT=========== //
const server = app.listen(3000, () => {
console.log("server is up and runned on port 3000");
});
// ===========SOCKET EXAMPLE =========== //
const io = socketIO(server);
io.on("connection", (socket) => {
// логування на бекенді
console.log("Socket is connected..");
// відправка в консоль на фронтенд із бекенду
socket.emit("message", { msg: "Hello from socket!" });
socket.on("custom event", (data) => {
console.log(data);
});
});
module.exports = server;
А фронтенд відпрацюємо із статичних файдів
у папці static створимо файл chat.html
і в ньому створимо верстку чату, але зараз головне, зоб фронтенд і бекенд обмінядися подіями і месеждами
<!-- Код верстки -->
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io.connect('http://localhost:3000');
socket.on('message', (data) => {
console.log(data);
// відправка в консоль на бекенд із фронтенду
socket.emit('custom event', { msg: 'Hello from client!' });
});
</script>
а після цього запустити сервер і зайти в браузер http://localhost:3000/chat.html
то в консолі як на сервері так і в браузері побачимо обмін повідомленнями.
ПОРЕФАКТОРИМО БЕКЕНД РОЗШИРИМО ФУНКЦІЇ
НАПИШЕМО ЧАТ
створимо на бекенді і фронтенді кастомний івент "message"
прим connect - це дефолтний івент
io.on("connection", (socket) => {
socket.on("message", (msg) => {
console.log(`Message from client: ${msg}`);
io.emit("message", msg);
});
});
фронт
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h1>Static page</h1>
<p>Socket io example</p>
<div class="container">
<ul id="messages"></ul>
<form id="msgForm">
<div class="input-group">
<input id="msg" type="text" autocomplete="false" />
<button type="submit">send</button>
</div>
</form>
</div>
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io.connect("http://localhost:3000");
document.getElementById("msgForm").addEventListener("submit", (event) => {
event.preventDefault();
const msgField = document.getElementById("msg");
socket.emit("message", msgField.value);
msgField.value = "";
});
socket.on("message", (msg) => {
const messages = document.getElementById("messages");
messages.insertAdjacentHTML("afterbegin", `<li>${msg}</li>`);
});
socket.on("connect", () => {
socket.emit("message", "new user connected..");
});
</script>
</body>
</html>
в цьому прикладі бекенд приймає повідомлення з форми при сабміті і одразу відправляє по події його назад клієнту.
А у фронті він чекає на подію message і як тільки вона відбувається виводить у список отримане повідомлення крім того. дефолтна подія connect при приєднанні нового користувача видасть нове повідомлення у всі х у кого відкритий цей фронт.
примітка: тут можна прописати стилі для фронта для краси
ПОРЕФАКТОРИМО. СТВОРИМО РУМИ. І БУДЕМО КОНЕКТИТИСЬ НЕ ДО ОДНОГО ЗАГАЛЬНОГО ЧАТУ А ДО РІЗНИХ КІМНАТ і вводити імʼя юзера
створимо для фронти у папці статік новий файли javascript.html і python.html для різних кімнат для спілкування.
також у файдах створимо другу форму для логіна. а офновна форма буле неактивна. при вході до долучення до чату спочатку залогінимося а потім тільки буде можливість віжправляти повідомлення
на сервері можна завести кілька сокетів namespace
бекенд
const nodeNameSpace = io.of('/nodeNameSpace');
nodeNameSpace.on('connection', (socket) => {
socket.on('join', (data) => {
socket.join(data.room);
nodeNameSpace
.in(data.room)
.emit('message', { msg: `${data.nick ? '' : 'New user '}joined ${data.room} room`, nick: data.nick });
});
socket.on('message', (data) => {
nodeNameSpace.in(data.room).emit('message', { msg: data.msg, nick: data.nick });
});
});
У цьому коді ми робимо все як і раніше, тільки ще ділимо по "кімнатах"
nodeNameSpace - приходитиме з фронту - кямната до якої ми приєднаємося при ешені on отримуємо data.room і за допомогою метода join приєднуємося до тієї кімнати
після цього тільки у цій кімнаті повертаємо повідомлення за допомогоюб метода emit.
далі у випалку виникнення події message ми отримуємо data і повертаємо в той же рум повідомлення.
тепер пропишемо фронт кімнати javascript.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
html {
margin: 0;
padding: 0;
}
body {
background-color: bisque;
margin: 0;
padding: 0;
}
h1,
p {
text-align: center;
}
.container {
width: 100rem;
margin: 0 auto;
}
ul {
border: 1px solid orangered;
border-radius: 0.5rem;
background-color: white;
height: 60vh;
list-style: none;
padding: 1rem;
overflow-y: auto;
display: flex;
flex-direction: column-reverse;
}
li {
font-size: 1.3rem;
color: lightslategray;
}
.input-group {
display: flex;
justify-content: space-between;
height: 3rem;
}
.input-group input {
border: 1px solid lightcyan;
outline: none;
width: 100%;
margin-right: 2rem;
padding: 0 1rem;
border-radius: 0.5rem;
display: block;
}
.input-group input::placeholder {
color: lightslategray;
font-family: serif;
}
.input-group button {
border: none;
outline: none;
background-color: darkred;
padding: 0 3rem;
border-radius: 0.5rem;
color: white;
text-transform: uppercase;
font-size: 1rem;
line-height: 1rem;
}
.inactive {
display: none;
}
</style>
</head>
<body>
<h1>Static page</h1>
<p>Socket io example</p>
<div class="container">
<ul id="messages"></ul>
<form id="msgForm" class="inactive">
<div class="input-group">
<input
id="msg"
type="text"
autocomplete="false"
placeholder="enter message"
/>
<button type="submit">send</button>
</div>
</form>
<form id="nickForm">
<div class="input-group">
<input
id="nick"
type="text"
autocomplete="false"
placeholder="enter your nickname"
/>
<button type="submit">join</button>
</div>
</form>
</div>
<script src="/socket.io/socket.io.js"></script>
<script>
let nick;
let socket;
const room = "javascript";
const initSocket = (room, nick) => {
socket = io.connect("/nodeNameSpace");
socket.on("message", ({ nick, msg }) => {
const messages = document.getElementById("messages");
messages.insertAdjacentHTML(
"afterbegin",
`<li><span style="color: orangered; font-style: italic">${nick}</span> ${msg}</li>`
);
});
socket.on("connect", () => {
socket.emit("join", { room, nick });
});
};
const nickForm = document.getElementById("nickForm");
const msgForm = document.getElementById("msgForm");
nickForm &&
nickForm.addEventListener("submit", (event) => {
event.preventDefault();
const nickField = document.getElementById("nick");
if (!nickField?.value) return;
nick = nickField.value;
initSocket(room, nick);
msgForm.classList.remove("inactive");
nickForm.classList.add("inactive");
});
msgForm &&
msgForm.addEventListener("submit", (event) => {
event.preventDefault();
const msgField = document.getElementById("msg");
socket.emit("message", { msg: msgField.value, room, nick });
msgField.value = "";
});
</script>
</body>
</html>
у кімнаті пайтон така сама верска тільки інша назва змінної room
Last updated