Коллеги, прошу опять помощи, как и писал выше после создания соединения, не могу вызывать sendMessage!!! как исправить????
|
ну выложи куда-нибудь проект, а то, из 4 "классов" показал только 2, как происходит инициализация и т.д. неизвестно
|
SuperZen, остальные не важны:
main.js - тут просто подключаются модули, будут проверки браузера и в конце запускается приложение Chat:
'use strict';
(function(window) {
document.addEventListener('DOMContentLoaded', function() {
const Chat = window.Chat;
const chat = new Chat;
chat.init();
});
})(window);
chat.js - это само приложение, в нем будет вся логика (пока что логика ws)))) вернее организовать подключение и дальнейшее использование в приложении) :
'use strict';
window.Chat = (function(window) {
const socketModule = window.SocketModule;
class Chat {
constructor() {
this.transport = new socketModule({
path: window.options.socketPath
});
}
init() {
this.transport.sendMessage('chat_message', {
type: 'text',
text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.'
});
}
}
return Chat;
})(window);
и собственно socketModule.js, логика его как и выше писал. :
'use strict';
window.SocketModule = (function(window) {
class SocketModule {
constructor() {
this.socket;
this.connection();
}
connection() {
const _t = this;
this.checkServer(function(server) {
if (!server) return;
_t.socket = new WebSocket('ws://server.localhost:5555');
_t.socket.addEventListener('open', function() {
_t.sendMessage('connection', {
client: true
});
_t.indicatorControl(true);
});
_t.socket.addEventListener('close', function() {
_t.indicatorControl(false);
_t.connection();
});
});
return this;
}
checkServer(callback) {
let timer;
const _t = this;
let count = 0;
timer = setInterval(function() {
const req = new XMLHttpRequest();
req.open('GET', '/api/connect', true);
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
req.send(null);
req.addEventListener('load', function() {
if (req.status === 200) {
clearInterval(timer);
callback(true);
}
});
count++;
if (count === _t.reconnectCount) {
clearInterval(timer);
console.log('Превышен лимит ожидания!');
}
}, 200);
return this;
}
sendMessage(event_name, data) { // event_name (string), data (string, array, object)
if (event_name.constructor.name === 'String') {
const _t = this;
this.readyStateConnection(function() {
_t.socket.send(JSON.stringify({event_name, data}));
});
} else return;
return this;
}
readyStateConnection(callback) {
let timer;
clearTimeout(timer);
if (this.socket.readyState === 1) {
callback();
} else {
const _t = this;
timer = setTimeout(function() {
_t.readyStateConnection(callback);
}, 0);
}
}
};
return SocketModule;
})(window);
Ну а результат res.render вот, но я думаю он не нужен особо: <!DOCTYPE html><html lang=ru><head><title>Тестим WebSockets</title><meta charset=UTF-8><meta name=viewport content="width=device-width,initial-scale=1"><link rel="shortcut icon" href="/images/favicon.png?v=2qx-wa3g2x" type=image/png><link rel=stylesheet href="/stylesheets/style.css?v=2tg-1rjnwfd"></head><body><noscript>Ваш браузер не поддерживает JavaScript. Включите или используйте другой браузер</noscript><section id=chat><div class=overlay><div id=chat_header><h2>Привет, anton</h2><a href=/logout class=logout>Выйти</a></div><div class=overflow><div id=messages><p>Сообщения в чате:</p><p id=no_messages>Сообщений нет</p></div><div id=users_list><p>Пользователи online</p><ul><li><p>marey</p></li></ul></div></div></div><div id=control_panel><form method=post id=send_message autocomplete=off><textarea name=message_text placeholder="ваше сообщение..."></textarea><button type=submit>Отправить</button></form></div></section><div id=server_message data-action=false></div></body><script src="/javascripts/options.js?v=5a-n5whjv"></script><script src="/javascripts/modules/SecureModule.js?v=8v-18pg8f1"></script><script src="/javascripts/modules/ServiceModule.js?v=1as-zlyrbi"></script><script src="/javascripts/modules/UserModule.js?v=uj-rhyhqe"></script><script src="/javascripts/modules/MessageModule.js?v=r3-m0w1dz"></script><script src="/javascripts/modules/socketModule.js?v=6jh-bhcxxf"></script><script src="/javascripts/Chat.js?v=q0-dpx5ol"></script><script src="/javascripts/main.js?v=dt-14wlng5"></script></html> |
this теряется когда вызываю checkServer в socketModule. Вернее я его сохраняю в _t а в this.socket самого модуля он не сохраняется.
Но тогда почему если сделать console.log(this); и console.log(this.socket); в методе sendMessage первое выведет socketModule в котором будет this.socket = экземпляру websocket (все правильно), а второе выведет undefined |
const chat = new Chat; не? https://developer.mozilla.org/ru/doc.../Operators/new const chat = new Chat(); |
Та и не нашёл, где там модули! То, что вы запихнули файлы в папку `modules` и, о ужас, дописали к имени переменной "Module", конечно же не сделает из них ни каким автомагическим способом модули. (также они все глобальны у вас, но странности вида `const Chat = window.Chat;` тоже зачем-то встретились)
Чтобы указать входную точку для вашей программы, используйте атрибут type со значением module <script src="/javascripts/main.js" type="module"></script>И это единственное, что вам нужно указать в вашем html. const chat = new Chat; chat.init();Так и представил, что было если было бы так: const array = new Array; array.init();Так что почему бы не просто `const chat = new Chat;`? Используйте стрелочные функции, тогда не придётся писать такое `const _t = this;` Можно просто `event_name.constructor === String` `this.socket.readyState === 1` WTF??? Почему не `this.socket.readyState === this.socket.OPEN` мне пришлось посмотреть в документации, что такое 1 У вас в SocketModule.prototype.readyStateConnection переменная timer всегда новая, так что старый таймер невожможно остановить У вас в chat.js передается `path: options.socketPath`, но в socketModule.js не используется... Вместо класса XMLHttpRequest можно использовать функцию fetch. Ваш /api/connect может возвратить не только 200 но и 304 (может быть, у меня именно так и произошло), почему бы не проверять так `response.status >= 200 && response.status < 400`, или даже `response.ok` (если используете fetch) `this.socket;` почему бы не (однако это ужасно, кто знает как лучше?)
this.socket = {
readyState: WebSocket.prototype.CLOSED
};
тогда не будет неожиданных ошибок связанных тем, что this.socket равен null Это и была главная причина!Вот исправленный код, исправленный с учётом сказанного выше, и модули тоже используются (а не переменные с именем, содержащим "Module") В index.html теперь только нужно, то что касается скриптов <script src="/javascripts/main.js" type="module"></script> main.js
import Chat from "./Chat.js";
document.addEventListener("DOMContentLoaded", () => {
const chat = new Chat;
});
options.js Я использовал этот сервер для теста, у вас там должно быть что-то другое
export default {
socketPath: "wss://echo.websocket.org"
};
Chat.js
import Socket from "./modules/socketModule.js";
import options from "./options.js";
export default class Chat {
constructor() {
this.transport = new Socket({
path: options.socketPath
});
// FIXME в отдельный модуль это я проверил как оно работает если текст в текстовое поле ввести и отправить
document.addEventListener("click", event => {
if(event.target.matches("#send_message [type='submit']")) {
event.preventDefault();
this.transport.sendMessage('chat_message', {
type: 'text',
text: document.querySelector("[name='message_text']").value
});
}
})
this.transport.sendMessage('chat_message', {
type: 'text',
text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.'
});
}
}
modules/socketModule.js
export default class SocketModule {
constructor({ path }) {
this.socket = {
readyState: WebSocket.prototype.CLOSED
};
this.connection();
this.path = path;
}
connection() {
this.checkServer(server => {
if (!server) return;
this.socket = new WebSocket(this.path);
this.socket.addEventListener('open', () => {
this.sendMessage('connection', {
client: true
});
this.indicatorControl = true;
});
this.socket.addEventListener("message", event => {
// FIXME логику разбора в отдельный модуль
const { event_name, data } = JSON.parse(event.data);
if(event_name === "chat_message") {
var p = document.createElement("p");
p.textContent = data.text;
document.getElementById("messages").append(p);
}
});
this.socket.addEventListener('close', () => {
this.indicatorControl = false;
this.connection();
});
});
return this;
}
set indicatorControl(value) {
// что-то делает
}
checkServer(callback) {
let timer;
let count = 0;
timer = setInterval(function() {
fetch("/api/connect", {
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
}).then(response => {
if(response.ok) {
clearInterval(timer);
callback(true);
}
});
count++;
if (count === this.reconnectCount) {
clearInterval(timer);
console.log('Превышен лимит ожидания!');
}
}, 200);
return this;
}
sendMessage(event_name, data) { // event_name (string), data (string, array, object)
if (event_name.constructor === String) {
this.readyStateConnection(() => {
console.log(event_name, data);
this.socket.send(JSON.stringify({ event_name, data }));
});
} else
return;
return this;
}
readyStateConnection(callback) {
if (this.socket.readyState === this.socket.OPEN) {
callback();
} else {
setTimeout(() => {
this.readyStateConnection(() => callback());
}, 0);
}
}
};
Но очень там не сердитесь, что я всё исправил на модули, как описано в стандарте JavaScript. UPD В readyStateConnection всё-таки не нужно стирать таймер, а то сообщения отправленные до подключения не отправятся. Исправил код выше(modules/socketModule.js) |
Malleys, +100500 к вашей карме))))))))) Щас посмотрим!!!!!
|
Malleys, про автомагию это потому что толковых учебных пособий нету, где все и вся будет рассказано)))))))))))))))))))) поэтому приходится учиться как получается к сожалению
|
А авторы учебников откуда узнают?
Я не знаю как такое для обучения, но я уже прочитал спецификацию языка. Девятое издание. Большая часть конечно же взята из предыдущего издания. https://www.ecma-international.org/e...9.0/index.html Я не знаю как такое для обучения, но что есть в JavaScript`е и как работает, всё описано. Я не говорю, что вам именно так надо изучать, просто я так узнаю. |
Malleys, теперь по коду, который вы написали. Большое спасибо за помощь. Но!
в chat.js в конструкторе, после слушателя просто вызываем метод sendMessage и он не срабатывает! |
| Часовой пояс GMT +3, время: 21:26. |