Это протокол коммуникации, предоставляющий двусторонний, полнодуплексный канал связи между клиентом и сервером через одно соединение TCP. Он позволяет обмениваться данными в режиме реального времени, что делает его идеальным для приложений, требующих мгновенной передачи информации, таких как чаты, игры, финансовые системы и другие.
WebSockets обеспечивают полнодуплексное общение, позволяя серверу и клиенту отправлять данные друг другу в любое время.
В отличие от HTTP, где каждое запрос-ответное взаимодействие открывает и закрывает соединение, WebSocket поддерживает постоянное соединение, что позволяет мгновенно передавать данные.
WebSockets уменьшают накладные расходы на установление соединений и протоколирование запросов, что приводит к более низкой задержке и уменьшенному использованию ресурсов по сравнению с регулярными HTTP-запросами.
WebSockets поддерживают передачу не только текстовых данных, но и бинарных, что расширяет возможности их применения.
Соединение WebSocket начинается с "рукопожатия" по протоколу HTTP. Клиент отправляет запрос на установление соединения с сервером, используя заголовок
Upgrade
, чтобы переключиться с HTTP на WebSocket.Если сервер принимает запрос, он отвечает с подтверждением, и соединение переключается на протокол WebSocket. С этого момента канал связи открыт и доступен для двусторонней передачи данных.
Клиент и сервер могут обмениваться данными в любом направлении. Сообщения отправляются в рамках установленного соединения без необходимости повторного рукопожатия.
Соединение может быть закрыто любой стороной (клиентом или сервером) в любое время. Это может быть сделано по желанию или в случае ошибки.
const WebSocket = require('ws');
const server = new WebSocket.Server({ port: 8080 });
server.on('connection', (socket) => {
console.log('Client connected');
socket.on('message', (message) => {
console.log(`Received: ${message}`);
socket.send(`You said: ${message}`);
});
socket.on('close', () => {
console.log('Client disconnected');
});
});
console.log('WebSocket server is running on ws://localhost:8080');
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍36❤1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍6❤1
Это техника, используемая для реализации связи между клиентом и сервером в веб-приложениях, чтобы поддерживать обновление данных в реальном времени. В отличие от обычных HTTP-запросов, лонг-пулинг позволяет клиенту ждать ответа от сервера дольше, что помогает уменьшить задержку при получении новых данных.
Клиент отправляет HTTP-запрос к серверу.
Сервер не отвечает сразу, а задерживает ответ до тех пор, пока не появятся новые данные или не истечет таймаут.
Когда данные становятся доступными или истекает таймаут ожидания, сервер отправляет ответ клиенту.
Клиент обрабатывает полученные данные и немедленно отправляет новый запрос к серверу для получения следующих обновлений.
Сервер на Node.js с использованием
express
const express = require('express');
const app = express();
let messages = [];
let clients = [];
// Endpoint для отправки сообщений
app.post('/messages', (req, res) => {
const message = req.body.message;
messages.push(message);
// Уведомляем всех клиентов
clients.forEach(client => client.res.json({ message }));
clients = [];
res.status(200).send('Message sent');
});
// Endpoint для получения сообщений (лонг-пулинг)
app.get('/messages', (req, res) => {
if (messages.length > 0) {
res.json({ message: messages.pop() });
} else {
clients.push({ req, res });
}
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
Клиентский код на JavaScript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Long Polling Example</title>
</head>
<body>
<h1>Long Polling Example</h1>
<div id="messages"></div>
<script>
function pollMessages() {
fetch('/messages')
.then(response => response.json())
.then(data => {
const messageDiv = document.createElement('div');
messageDiv.textContent = `New message: ${data.message}`;
document.getElementById('messages').appendChild(messageDiv);
pollMessages(); // Отправляем новый запрос после получения сообщения
})
.catch(error => {
console.error('Error:', error);
setTimeout(pollMessages, 5000); // Повторный запрос через 5 секунд при ошибке
});
}
// Начинаем лонг-пулинг
pollMessages();
</script>
</body>
</html>
Лонг-пулинг позволяет получать данные в реальном времени без необходимости постоянно проверять сервер с частыми запросами.
По сравнению с обычным пулингом (когда клиент постоянно отправляет запросы с фиксированным интервалом), лонг-пулинг уменьшает количество HTTP-запросов, что снижает нагрузку на сервер.
Лонг-пулинг легче внедрить и поддерживать в сравнении с более сложными технологиями, такими как WebSockets.
Хотя лонг-пулинг уменьшает задержку по сравнению с обычным пулингом, он все же может иметь небольшие задержки в зависимости от времени ожидания и частоты событий.
Держание соединений открытыми в течение длительного времени может быть ресурсоемким для сервера, особенно при большом количестве клиентов.
Лонг-пулинг менее эффективен по сравнению с WebSockets, которые предоставляют постоянное двустороннее соединение.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤5🔥3😁2
State manager — это инструмент или библиотека для управления состоянием приложения, особенно в сложных проектах с большим количеством взаимозависимых данных. Популярные state manager’ы включают Redux, MobX и Zustand для React-приложений, обеспечивающие централизованное хранение и управление состоянием. Они помогают структурировать данные, отслеживать их изменения и синхронизировать их между компонентами.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍22🔥8❤1
Это процесс проверки подлинности пользователя, который пытается получить доступ к системе или ресурсу. Веб-приложения и сервисы обычно используют несколько методов аутентификации для обеспечения безопасности и защиты данных.
Пользователь вводит имя пользователя и пароль, которые проверяются на сервере. Веб-сайты с формой входа, требующей логин и пароль.
После успешного входа пользователь получает токен (например, JWT), который используется для дальнейших запросов. API, использующие токены для проверки подлинности запросов.
Протокол авторизации, позволяющий сторонним приложениям получать ограниченный доступ к ресурсам пользователя без передачи пароля. Вход через Google, Facebook или другие социальные сети.
Требует два различных типа проверки (например, пароль и одноразовый код). Вход с использованием пароля и SMS-кода.
Использует биометрические данные (например, отпечатки пальцев или распознавание лиц) для проверки подлинности. Вход через Touch ID или Face ID на мобильных устройствах.
npm install express jsonwebtoken bcryptjs body-parser
const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const bodyParser = require('body-parser');
const app = express();
const PORT = 3000;
const SECRET_KEY = 'your_secret_key';
let users = []; // Для простоты используем массив в памяти
app.use(bodyParser.json());
// Регистрация пользователя
app.post('/register', async (req, res) => {
const { username, password } = req.body;
const hashedPassword = await bcrypt.hash(password, 8);
users.push({ username, password: hashedPassword });
res.status(201).send('User registered');
});
// Вход пользователя
app.post('/login', async (req, res) => {
const { username, password } = req.body;
const user = users.find(u => u.username === username);
if (!user) {
return res.status(404).send('User not found');
}
const isPasswordValid = await bcrypt.compare(password, user.password);
if (!isPasswordValid) {
return res.status(401).send('Invalid password');
}
const token = jwt.sign({ username: user.username }, SECRET_KEY, { expiresIn: '1h' });
res.json({ token });
});
// Защищенный маршрут
app.get('/protected', (req, res) => {
const token = req.headers['authorization'];
if (!token) {
return res.status(401).send('Access denied');
}
try {
const decoded = jwt.verify(token, SECRET_KEY);
res.json({ message: 'Protected content', user: decoded });
} catch (err) {
res.status(401).send('Invalid token');
}
});
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32🔥3
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍27🔥3
GET-запросы отправляют данные через URL, который сохраняется в истории браузера. Это означает, что любой, кто имеет доступ к истории браузера, может увидеть эти данные.
Многие веб-серверы и прокси-серверы автоматически записывают URL всех запросов в свои логи. Чувствительная информация в URL будет сохранена в этих логах и может быть доступна администраторам серверов или в случае компрометации системы.
Браузеры, прокси-серверы и промежуточные серверы могут кэшировать URL-адреса GET-запросов. Это означает, что чувствительная информация может быть сохранена в кэшах и доступна при последующих обращениях.
Большинство браузеров и серверов имеют ограничения на длину URL (обычно около 2000 символов). Если данные слишком длинные, они могут быть обрезаны, что приведет к потере информации или ошибкам при обработке запроса.
Когда пользователь переходит по ссылке с одной страницы на другую, URL-адрес исходной страницы часто передается как заголовок Referer в HTTP-запросе. Это означает, что чувствительная информация в URL может быть передана сторонним сайтам.
Данные в GET-запросах передаются через URL, в то время как данные в POST-запросах передаются в теле запроса. URL более подвержены утечке, так как они часто видны в различных местах (например, в журналах серверов, истории браузера и т.д.).
Для отправки чувствительной информации лучше использовать POST-запросы, так как данные передаются в теле запроса и не сохраняются в URL.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Secure Form</title>
</head>
<body>
<form action="/submit" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="username">
<label for="password">Password:</label>
<input type="password" id="password" name="password">
<button type="submit">Submit</button>
</form>
</body>
</html>
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍25
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍26❤2🔥1
Это мера, которая оценивает сложность структуры и конструкции кода. Она часто используется для оценки понятности, поддерживаемости и вероятности ошибок в программном коде. Одним из наиболее известных методов измерения синтаксической сложности является цикломатическая сложность, предложенная Томасом Маккейбом в 1976 году.
Это количественная мера количества независимых путей через программу. Она используется для оценки сложности программного кода, измеряя количество логических ветвлений. Чем выше цикломатическая сложность, тем больше возможных путей исполнения и, следовательно, тем сложнее понять и протестировать программу.
Цикломатическая сложность может быть рассчитана с помощью следующей формулы:
V(G) = E - N + 2P
def example(a, b):
if a > 0:
if b > 0:
return a + b
else:
return a - b
else:
return b
Цикломатическая сложность
V(G)
будетV(G) = E - N + 2P
V(G) = 6 - 5 + 2*1
V(G) = 3
Чем выше сложность, тем труднее понять код. Программы с высокой сложностью требуют больше времени для анализа и понимания.
Код с высокой сложностью сложнее поддерживать и изменять. Это может привести к большему числу ошибок при внесении изменений.
Более сложный код требует большего количества тестов для покрытия всех возможных путей исполнения. Это увеличивает время и усилия, необходимые для тестирования.
Программы с низкой сложностью, как правило, более надежны и менее подвержены ошибкам, так как легче понимать и тестировать все возможные сценарии.
Разделение сложных функций на более простые и малые функции. Использование более простых и понятных конструкций.
Вынос повторяющегося кода в отдельные функции или методы.
Добавление пояснительных комментариев и документации для сложных участков кода.
Использование проверенных паттернов проектирования для упрощения и структурирования кода.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17❤1
Каждый элемент, атрибут или текстовый узел страницы представлен как узел дерева, что позволяет программам (например, через JavaScript) взаимодействовать с документом, изменять его содержимое и структуру.
DOM-дерево обеспечивает удобный способ управления элементами веб-страницы динамически.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍34🔥7❤1🤯1
Это два основных подхода к шифрованию данных. Они различаются по способу использования ключей для шифрования и дешифрования.
Использует один и тот же ключ как для шифрования, так и для дешифрования данных. Этот ключ должен быть известен как отправителю, так и получателю, что требует безопасного способа передачи ключа между ними.
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
# Генерация ключа
key = get_random_bytes(16) # 16 байт = 128 бит
# Создание шифра
cipher = AES.new(key, AES.MODE_EAX)
# Шифрование данных
data = b'Secret message'
nonce = cipher.nonce
ciphertext, tag = cipher.encrypt_and_digest(data)
print(f'Ciphertext: {ciphertext}')
# Дешифрование данных
cipher = AES.new(key, AES.MODE_EAX, nonce=nonce)
plaintext = cipher.decrypt_and_verify(ciphertext, tag)
print(f'Plaintext: {plaintext}')
Использует пару ключей: открытый ключ и закрытый ключ. Открытый ключ используется для шифрования данных и может быть свободно распространяем, в то время как закрытый ключ используется для дешифрования и должен оставаться в секрете. Это решает проблему передачи ключей, так как отправитель может зашифровать данные открытым ключом получателя, а только получатель сможет расшифровать их с помощью своего закрытого ключа.
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
# Генерация пары ключей
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
)
public_key = private_key.public_key()
# Шифрование данных
message = b'Secret message'
ciphertext = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print(f'Ciphertext: {ciphertext}')
# Дешифрование данных
plaintext = private_key.decrypt(
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print(f'Plaintext: {plaintext}')
Симметричная: Один ключ для шифрования и дешифрования.
Асимметричная: Пара ключей — открытый для шифрования и закрытый для дешифрования.
Симметричная: Требует безопасной передачи ключа, что может быть сложно.
Асимметричная: Обеспечивает безопасную передачу ключей через использование открытого ключа.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🤯1
Также учитываются сроки выполнения, доступные ресурсы и возможные риски.
Точный уровень определяется в зависимости от контекста и опыта команды или разработчика.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊19🔥5👍3
Это паттерн проектирования, который используется для управления зависимостями в программном обеспечении. Суть этого паттерна заключается в том, что объект получает свои зависимости извне, а не создаёт их сам. Это способствует более гибкому, легко тестируемому и поддерживаемому коду.
Принцип, согласно которому объект делегирует управление своими зависимостями внешнему источнику.
Конкретная реализация инверсии управления, при которой зависимости передаются объекту через конструктор, методы или свойства.
Зависимости передаются объекту через параметры его конструктора. Пример на Java:
public class Service {
private final Repository repository;
public Service(Repository repository) {
this.repository = repository;
}
public void performAction() {
repository.doSomething();
}
}
Зависимости передаются объекту через методы-сеттеры после его создания. Пример на Java:
public class Service {
private Repository repository;
public void setRepository(Repository repository) {
this.repository = repository;
}
public void performAction() {
repository.doSomething();
}
}
Зависимости передаются объекту через методы, определённые в интерфейсах. Пример на TypeScript:
interface IRepository {
doSomething(): void;
}
class Repository implements IRepository {
doSomething() {
console.log("Doing something...");
}
}
class Service {
private repository: IRepository;
constructor(repository: IRepository) {
this.repository = repository;
}
performAction() {
this.repository.doSomething();
}
}
const repository = new Repository();
const service = new Service(repository);
service.performAction();
Код становится более модульным и тестируемым, так как зависимости можно легко заменять на моки или стабы в тестах.
Уменьшается связность кода, что упрощает его поддержку и модификацию.
Легче менять реализации зависимостей, не изменяя код, который их использует.
Зависимости объектов становятся явными, что улучшает понимание кода.
Внедрение DI может усложнить код, особенно если используется слишком много уровней абстракции.
Понимание и правильное использование DI может потребовать времени и обучения, особенно для разработчиков, незнакомых с паттерном.
При внедрении большого числа зависимостей через конструктор конструктор может стать перегруженным.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу Знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍23🔥11💊1
Это принцип программирования, который передает управление выполнением программы из рук разработчика в руки фреймворка или контейнера. IoC позволяет создавать более гибкие, расширяемые и тестируемые приложения за счет отделения бизнес-логики от деталей инфраструктуры.
В традиционном подходе компоненты создают и управляют своими зависимостями напрямую. С IoC компоненты делегируют эту ответственность внешней системе.
Компоненты становятся более независимыми и легко заменяемыми, что способствует повторному использованию и тестируемости.
IoC может быть реализована несколькими способами, в том числе через Dependency Injection (внедрение зависимостей) и Service Locator (локатор служб).
Это наиболее распространенный способ реализации IoC, где зависимости объекта передаются ему извне, а не создаются внутри. Пример на Java с использованием Spring. В этом примере Spring фреймворк автоматически внедряет зависимость
Repository
в Service
через конструктор.import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Service {
private final Repository repository;
@Autowired
public Service(Repository repository) {
this.repository = repository;
}
public void performAction() {
repository.doSomething();
}
}
Это шаблон проектирования, который предоставляет центральное место для получения зависимостей. Компоненты запрашивают зависимости у локатора служб, вместо того чтобы создавать их напрямую. Пример на Java:
public class ServiceLocator {
private static final Map<Class<?>, Object> services = new HashMap<>();
public static <T> void registerService(Class<T> serviceClass, T service) {
services.put(serviceClass, service);
}
public static <T> T getService(Class<T> serviceClass) {
return serviceClass.cast(services.get(serviceClass));
}
}
// Использование Service Locator
ServiceLocator.registerService(Repository.class, new RepositoryImpl());
Repository repository = ServiceLocator.getService(Repository.class);
repository.doSomething();
IoC позволяет легко заменять реальные зависимости на моки или стабы в тестах.
Компоненты становятся менее зависимыми друг от друга, что упрощает их замену и модификацию.
Легко добавлять новые зависимости или изменять существующие без изменения кода, использующего эти зависимости.
Зависимости становятся явными, что улучшает понимание и документирование системы.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥20👍16
Однопоточность и многопоточность имеют свои преимущества и недостатки в различных сценариях. В зависимости от конкретной задачи и условий, однопоточность может быть предпочтительнее многопоточности.
Однопоточные приложения обычно проще разрабатывать и отлаживать, так как не нужно учитывать проблемы, связанные с синхронизацией и состоянием, такие как гонки данных, взаимные блокировки и другие сложности, возникающие при многопоточности. Простые скрипты и утилиты, которые выполняют линейную последовательность операций. Приложения, которые не требуют высокой производительности или быстрого времени отклика.
Если задача не требует параллельного выполнения или если она не может быть эффективно распараллелена, однопоточность может быть предпочтительнее, так как многопоточность не принесет значительных преимуществ. Задачи с высокой степенью последовательности, где каждый шаг зависит от завершения предыдущего шага. Приложения с низкой нагрузкой, где обработка данных занимает мало времени.
В некоторых системах ресурсы, такие как память и процессорное время, ограничены. Однопоточные приложения потребляют меньше ресурсов, так как они не требуют создания и управления несколькими потоками. Встроенные системы и устройства с ограниченными вычислительными ресурсами. Простые IoT устройства, где использование многопоточности может быть излишним.
Однопоточные приложения имеют более предсказуемое поведение, так как отсутствует конкуренция между потоками. Это особенно важно для задач, где требуется строгая последовательность выполнения. Реализация алгоритмов, требующих строгой последовательности шагов. Критические системы, где некорректное выполнение может привести к серьезным последствиям.
Управление потоками имеет свои накладные расходы: создание, переключение контекста и синхронизация потоков. В некоторых случаях эти накладные расходы могут перевесить преимущества многопоточности. Приложения с короткими и нечастыми задачами, где накладные расходы на многопоточность не оправданы. Приложения, работающие в условиях высокой конкуренции за ресурсы, где использование нескольких потоков может привести к деградации производительности.
Node.js использует однопоточную модель с событиями и обратными вызовами для обработки запросов. Благодаря асинхронной модели ввода-вывода, Node.js может эффективно обрабатывать большое количество одновременных соединений, не создавая новые потоки для каждого запроса.
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, world!\n');
});
server.listen(3000, () => {
console.log('Server running at http://localhost:3000/');
});
Для простых задач, таких как чтение и обработка файла, однопоточность может быть вполне достаточной и проще в реализации.
def process_file(file_path):
with open(file_path, 'r') as file:
data = file.read()
# Обработка данных
print(data)
if __name__ == '__main__':
process_file('example.txt')
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31❤2
Это подход к управлению событиями в приложениях, который подразумевает обработку всех событий в одном месте или с использованием единого механизма. Это помогает упростить управление событиями, повысить поддерживаемость и улучшить масштабируемость приложения. Этот подход особенно полезен в сложных приложениях, где множество компонентов взаимодействуют друг с другом через события.
В приложениях, использующих Vue.js, централизованное управление состоянием и событиями часто реализуется с помощью Vuex. Vuex позволяет управлять состоянием приложения и событиями в одном месте.
// store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
message: ''
},
mutations: {
setMessage(state, message) {
state.message = message;
}
},
actions: {
updateMessage({ commit }, message) {
commit('setMessage', message);
}
}
});
// Component.vue
<template>
<div>
<input v-model="message" @input="updateMessage(message)">
<p>{{ message }}</p>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
computed: {
...mapState(['message'])
},
methods: {
...mapActions(['updateMessage'])
}
};
</script>
Это библиотека для управления состоянием в приложениях React, которая также предоставляет централизованный механизм для управления событиями и состоянием.
// actions.js
export const setMessage = message => ({
type: 'SET_MESSAGE',
payload: message
});
// reducer.js
const initialState = {
message: ''
};
const reducer = (state = initialState, action) => {
switch (action.type) {
case 'SET_MESSAGE':
return {
...state,
message: action.payload
};
default:
return state;
}
};
export default reducer;
// store.js
import { createStore } from 'redux';
import reducer from './reducer';
const store = createStore(reducer);
export default store;
// Component.js
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { setMessage } from './actions';
const Component = () => {
const message = useSelector(state => state.message);
const dispatch = useDispatch();
const handleChange = (event) => {
dispatch(setMessage(event.target.value));
};
return (
<div>
<input value={message} onChange={handleChange} />
<p>{message}</p>
</div>
);
};
export default Component;
В Node.js можно использовать
EventEmitter
для централизованного управления событиями.const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
// Обработчик события
myEmitter.on('event', (message) => {
console.log('Received:', message);
});
// Генерация события
myEmitter.emit('event', 'Hello, World!');
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍27🔥13🤯2