javascript
27 декабря 2022 г. 9:32
Websockets
ws, WebSocket - протокол для общения между клиентом и сервером, предоставляющий двухсторонне общение сверх протокола TCP.
Мы подключаем WebSocket один раз, а затем сервер может отдавать нам ответы тогда, когда посчитает нужным.
Сначала отправляется обычный TCP-запрос на сервер и ждём от него ответа. Такой процесс называется “рукопожатие” (Handshake) (используется также при подключении к роутеру). Затем после получении ответа идёт переключение протокола на WebSocket, сигнализируя о том, что сервер будет присылать ответы множество раз.
Пример:
// Отправляем запрос серверу по ссылке example.com/connect-to-ws // Вот что примерно мы пришлём: GET /connect-to-ws HTTP/1.1 Host: example.com:8000 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Sec-WebSocket-Version: 13 // А вот что нам на такой запрос ответит сервер при успешном рукопожатии: HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Особенности WS:
- Поддерживает двухсторонее соединение в реальном времени
- Отправляет заголовок только один раз
- Нет ограничений, связанных с кросс-доменными запросами
- Могут отправлять/получать как строки, так и бинарные данные
API
Методы:
- socket.send(data),
- socket.close([code], [reason]).
События:
- open,
- message,
- error,
- close.
Привязка контекста к функции
let boundFunc = func.bind(context);
Результатом вызова func.bind(context) является особый «экзотический объект» (термин взят из спецификации), который вызывается как функция и прозрачно передаёт вызов в func, при этом устанавливая this=context.
Другими словами, вызов boundFunc подобен вызову func с фиксированным this.
Например, здесь funcUser передаёт вызов в func, фиксируя this=user:
let user = { firstName: "Вася" }; function func() { alert(this.firstName); } let funcUser = func.bind(user); funcUser(); // Вася
let user = { firstName: "Вася", say(phrase) { alert(`${phrase}, ${this.firstName}!`); } }; let say = user.say.bind(user); say("Привет"); // Привет, Вася (аргумент "Привет" передан в функцию "say") say("Пока"); // Пока, Вася (аргумент "Пока" передан в функцию "say")
Частичное применение
let bound = func.bind(context, [arg1], [arg2], ...);
function mul(a, b) { return a * b; } let double = mul.bind(null, 2); alert( double(3) ); // = mul(2, 3) = 6 alert( double(4) ); // = mul(2, 4) = 8 alert( double(5) ); // = mul(2, 5) = 10
Частичное применение без контекста
function partial(func, ...argsBound) { return function(...args) { // (*) return func.call(this, ...argsBound, ...args); } } // использование: let user = { firstName: "John", say(time, phrase) { alert(`[${time}] ${this.firstName}: ${phrase}!`); } }; // добавляем частично применённый метод с фиксированным временем user.sayNow = partial(user.say, new Date().getHours() + ':' + new Date().getMinutes()); user.sayNow("Hello"); // Что-то вроде этого: // [10:00] John: Hello!
Можем ли мы изменить this дополнительным связыванием?
function f() { alert(this.name); } f = f.bind( {name: "Вася"} ).bind( {name: "Петя" } ); f();
Ответ: Вася.
Экзотический объект bound function, возвращаемый при первом вызове f.bind(...), запоминает контекст (и аргументы, если они были переданы) только во время создания.
Следующий вызов bind будет устанавливать контекст уже для этого объекта. Это ни на что не повлияет.
Можно сделать новую привязку, но нельзя изменить существующую.
Примеры
Пример 1
function f() { alert(this.name); } f = f.bind( {name: "Вася"} ).bind( {name: "Петя"} ); f(); // Вася
Экзотический объект bound function
, возвращаемый при первом вызове f.bind(...)
, запоминает контекст (и аргументы, если они были переданы) только во время создания.
Следующий вызов bind
будет устанавливать контекст уже для этого объекта. Это ни на что не повлияет.
Можно сделать новую привязку, но нельзя изменить существующую.
Пример 2
function askPassword(ok, fail) { // let password = prompt("Password?", ''); let password = "rockstar"; if (password == "rockstar") ok(); else fail(); } let user = { name: 'Вася', loginOk() { console.log(`${this.name} logged in`); }, loginFail() { console.log(`${this.name} failed to log in`); }, }; let login_ok = user.loginOk.bind(user); let login_fail = user.loginFail.bind(user); askPassword(login_ok, login_fail);
Пример 3
function askPassword(ok, fail) { // let password = prompt("Password?", ''); let password = "rockstar"; if (password == "rockstar") ok(); else fail(); } let user = { name: 'John', login(result) { console.log( this.name + (result ? ' logged in' : ' failed to log in') ); } }; askPassword(user.login.bind(user, true), user.login.bind(user, false));
Такой же результат через partial
.
function partial(func, ...argsBound) { return function(...args) { // (*) return func.call(this, ...argsBound, ...args); } } function askPassword(ok, fail) { // let password = prompt("Password?", ''); let password = "rockstar"; if (password == "rockstar") ok(); else fail(); } let user = { name: 'John', login(result) { console.log( this.name + (result ? ' logged in' : ' failed to log in') ); } }; user.ok = partial(user.login.bind(user), true) user.fail = partial(user.login.bind(user), false) askPassword(user.ok, user.fail);
Отличие preventDefault от stopPropagation?
preventDefault
запрещает стандартное поведение элемента.
Примеры:
1. Клик на кнопку submit производит отправку формы, но preventDeafult()
это прекратит.
2. Нажатие на ссылку перенаправляет на другую страницу, но preventDefault()
запретит это действие.
stopPropagation
запрещает передачу события от ребенка к родителю. Другими словами, если мы кликнули по вложенному элементу, его родитель "не почувствует" этого нажатия.
Пример:
Кнопки поверх картинки в слайдере на странице покупки товара. Если кликаем по картинке, открывается во весь экран, но если по кнопке, то какое-то другое действие, например, заказать товар.
Источники
- https://habr.com/ru/sandbox/171066/
- https://learn.javascript.ru/websocket
- https://learn.javascript.ru/bind
Представляю вашему вниманию книгу, написанную моим близким другом Максимом Макуриным: Секреты эффективного управления ассортиментом.
Книга предназначается для широкого круга читателей и, по мнению автора, будет полезна специалистам отдела закупок и логистики, категорийным и финансовым менеджерам, менеджерам по продажам, аналитикам, руководителям и директорам, в компетенции которых принятие решений по управлению ассортиментом.
Комментарии: 0