Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   websocket на стороне клиента (https://javascript.ru/forum/misc/75257-websocket-na-storone-klienta.html)

Роман Андреевич 17.09.2018 12:12

websocket на стороне клиента
 
Коллеги, доброго времени суток,
суть проблемы такова. Пишу приложение и вэбсокетами. Встал на клиенте. Точнее встал над recconect
Вот код:

'use strict';
window.SocketModule = ((window) => {
        
    class SocketModule {
        
        constructor(options) {
            
            this.path = options.path;
            this.reconnectNumber = 0;
            this.connection();
            
        }
        
        /*
         *  connection - установить соединение
         *      connectionStatus,
         *      
         *  disconnection - остановить соединение
         *  reconnection - пересоединение
         *  
         *  send - отправить сообщение
         *  accept - принять сообщение
         *  
         */
        
        connection() {
            
            this.socket = new WebSocket(this.path);
                
                this.socket.addEventListener('open', (e) => {

console.log('connection...);
                    
                    this.send('checkConnection', {

                        connect: true

                    });
                    
                    
                    
                });
                
                this.socket.addEventListener('close', (e) => {

console.log('reconnection... please wait...');
                    
                    this.connection(this.path);
                    
                });

        }
        
        send(event_name, data) { // event_name (string), data (string, array, object)

            if (event_name.constructor.name === 'String') {
                
                let _this = this;
                
                this.wait(function() {
                
                    _this.socket.send(JSON.stringify({event_name, data}));

                }, 0);
                
            } else return;
            
        }
        
        wait(callback, time) {
            
            let timer;
            clearTimeout(timer);
            
            if (this.socket.readyState === 1) {
                callback();
            } else {
                let _this = this;
                timer = setTimeout(function() {
                    _this.wait(callback, time);
                }, time);
            }
        }
    
    };
    
    return SocketModule;

})(window);


Создается экземпляр класса websocket и на него навешивается события open и close. По событию close происходит рекурсивный вызов этой же функции. В консоль падает сообщение : WebSocket connection to 'ws://server.localhost:5555/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED - так и должно быть. После включения сервера связь появляется, все ок.

Но у меня вопрос, может кто делал или словом подскажет. Как избежать данного сообщения??? Или может, как сделать reconnect???

Роман Андреевич 17.09.2018 12:14

Проблема, даже не в сообщении, а в том, что увеличивается время каждого следующего переподключения

ruslan_mart 17.09.2018 12:41

Цитата:

let timer;
clearTimeout(timer);
Так Вы тут по факту заново заводите переменную таймера, которая равна undefined.

Сохраняйте ID таймаута в this.



wait(callback, time) {
             
            clearTimeout(this._timer);
             
            if (this.socket.readyState === 1) {
                callback();
            } else {
                this._timer = setTimeout(() => this.wait(callback, time), time);
            }
        }

Роман Андреевич 17.09.2018 12:51

ruslan_mart, ничего не поменялось, задержки те же самые.

SuperZen 17.09.2018 13:00

взял тут https://socket.io/docs/client-api/#n...er-url-options
<table>
  <thead>
    <tr>
      <th>Option</th>
      <th>Default value</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>path</code></td>
      <td><code>/socket.io</code></td>
      <td>name of the path that is captured on the server side</td>
    </tr>
    <tr>
      <td><code>reconnection</code></td>
      <td><code>true</code></td>
      <td>whether to reconnect automatically</td>
    </tr>
    <tr>
      <td><code>reconnectionAttempts</code></td>
      <td><code>Infinity</code></td>
      <td>number of reconnection attempts before giving up</td>
    </tr>
    <tr>
      <td><code>reconnectionDelay</code></td>
      <td><code>1000</code></td>
      <td>how long to initially wait before attempting a new reconnection (<code>1000</code>). Affected by +/- <code>randomizationFactor</code>,
        for example the default initial delay will be between 500 to 1500ms.</td>
    </tr>
    <tr>
      <td><code>reconnectionDelayMax</code></td>
      <td><code>5000</code></td>
      <td>maximum amount of time to wait between reconnections (<code>5000</code>). Each attempt increases the reconnection
        delay by 2x along with a randomization as above</td>
    </tr>
    <tr>
      <td><code>randomizationFactor</code></td>
      <td><code>0.5</code></td>
      <td>0 &lt;= randomizationFactor &lt;= 1</td>
    </tr>
    <tr>
      <td><code>timeout</code></td>
      <td><code>20000</code></td>
      <td>connection timeout before a <code>connect_error</code> and <code>connect_timeout</code> events are emitted</td>
    </tr>
    <tr>
      <td><code>autoConnect</code></td>
      <td><code>true</code></td>
      <td>by setting this false, you have to call <code>manager.open</code> whenever you decide it’s appropriate</td>
    </tr>
    <tr>
      <td><code>query</code></td>
      <td><code>{}</code></td>
      <td>additional query parameters that are sent when connecting a namespace (then found in <code>socket.handshake.query</code>        object
        on the server-side)</td>
    </tr>
  </tbody>
</table>


Each attempt increases the reconnection delay by 2x along with a randomization as above

Роман Андреевич 17.09.2018 13:17

SuperZen, спасибо, но socket io в данном случае не подходит

SuperZen 17.09.2018 13:46

а, что-то не увидел ) что не socket.io -

да, vanilla websocket не имеет таких настроек по дефолту ) как socket.io

https://github.com/websockets/ws/wik...auto-reconnect

https://stackoverflow.com/questions/...s-in-websocket

https://github.com/joewalnes/reconnecting-websocket - древнее какое-то оно, но как идея )

а почему не сделать на socket.io, ? или бэк на другом языке?

Роман Андреевич 17.09.2018 13:54

SuperZen, да подходит, только у меня подразумевается cluster, а там еще в настройках не разбирался, по всей видимости буду использовать именно socket io. Но с другой стороны, в моем случае проблема в сообщении, которое прилетает в консоль WebSocket connection to 'ws://server.localhost:5555/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED. Подключение восстанавливается но с задержкой, и чем дольше выключен сервер, тем больше эта задержка, фотку не могу вставить в сообщение, почему с компа не дает???????
В socket io есть лишнее. Мне в проекте нужны только websockets, а там все транспорты, ws + ajax и тд, он сам проверяет на доступность. Мне нужно по идее, только подключение по ws. От сюда и решил сам написать модуль.

Можно конечно воткнуть ajax, для проверки доступности сервера...

Белый шум 17.09.2018 14:15

Цитата:

Сообщение от Роман Андреевич (Сообщение 494847)
Проблема, даже не в сообщении, а в том, что увеличивается время каждого следующего переподключения

А увеличение времени задержки происходит, случайно, не в фоновой вкладке (либо когда сам браузер свёрнут/перекрыт другим приложением)??

Если да, то это оптимизации браузера - вроде сафари так делает, тогда как файрфокс с хромом просто повышают задержку до 1 секунды. В таком случае надо перенести setTimeout в веб-воркер: https://github.com/mohayonao/worker-timer

Роман Андреевич 17.09.2018 14:23

Белый шум, все верно, браузер увеличивает задержку примерно на 1 секунду (в хроме сижу), и через 50 попыток соединиться, я включаю сервер и жду пока клиент подключится.

если не вешать слушалку событий то ничего не вылетает (я про сообщения, но и не могу в браузере дать пользователю понять что связи нет)))))))))

с аяком проще, там 502 и все норм, а тут есть только статус, и слушалка (addeventlistener) но при close вылетает сразу ошибка

Роман Андреевич 17.09.2018 14:25

Еще вопрос, может кто знает, как закрыть соединение????? принудительно.

Вопрос, к тому, что по событию close делаю this.spcket = null, а потом вызываю опять connection то все равно ничего выходит

SuperZen 17.09.2018 16:03

https://developer.mozilla.org/ru/doc...bSocket#close()

Роман Андреевич 18.09.2018 12:20

коллеги, всем спасибо, решил задачу.
Все работает, отлично и быстро

SuperZen 18.09.2018 14:08

что сделал то?)

Роман Андреевич 18.09.2018 14:23

SuperZen, радость была преждевременной)))))))))))))))

Дабы исключить ошибку соединения сокета, я перед созданием экземпляра, пульнул ajax на сервер, и если он мне вернул код 200 то все ок, создаем и вешаем слушатели open и close. по событию close просто снова вызываем connection. Вот код:

'use strict';
window.SocketModule = (function(window) {
        
    class SocketModule {
        
        constructor(options) {
            
            this.socket;
            this.path = options.path;
            this.connection();
            this.reconnectCount = 60;
            
        }
        
        connection() {
            
            const _t = this;
            
            this.checkServer(function(server) {
                
                if (!server) return;
                
                _t.socket = new WebSocket(_t.path);
                
                _t.socket.addEventListener('open', function() {

                    _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) {

            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);


НО!!!!!!!!!!!!!!!!!!!!!!!!!))))))))))))))))))))) )

Когда я вызываю метод sendMessage в другом классе:

'use strict';
window.Chat = (function(window) {
    
    const options = window.options;
    const socketModule = window.SocketModule;
    const ServiceModule = window.ServiceModule;
    const MessageModule = window.MessageModule;
    
    class Chat {
        
        constructor() {
            
            this.transport = new socketModule({
                
                path: options.socketPath
                
            });
            
        }
        
        init() {
            
            this.transport.sendMessage('chat_message', {
                
                type: 'text',
                text: 'Lorem ipsum dolor sit amet, megatron7000'
            
            });
            
            
            
        }
        
    }
    
    return Chat;
    
})(window);


Эта шайтан машина))) выдает мне - annot read property 'send' of undefined! В методе readyStateConnection this.socket = undefined!!!! если вывести в консоль this, то он есть, а если this.socket его нет.

Роман Андреевич 18.09.2018 14:25

Теперь встал вопрос в том, видимо где я потерял контекст???????!!!!!!!!!! или просто туплю сижу.

SuperZen 19.09.2018 00:37

server.js
var path = require('path')
var http = require('http')
var express = require('express')
var WebSocket = require('ws')

const app = express()
const httpServer = http.createServer(app)
const wss = new WebSocket.Server({ server: httpServer })

app.use(express.static(path.join(__dirname, 'public')))

app.get('/', function (req, res) {
  res.sendfile(path.join(__dirname, 'public', 'index.html'))
})

wss.on('connection', (client) => {
  client.on('message', (message) => {
    console.log('message: ', message)
    client.send('ok')
  })
  client.send('connected')
})

httpServer.listen(2999, () => {
  console.log('started at http://localhost:2999')
})


public/index.html
<html>

<head>

</head>

<body>
  <div id="connection">not connected</div>
  <button id="button">Send</div>
    <script>
      var connection = document.getElementById('connection')
      document.getElementById('button').addEventListener('click', function () {
        ws.send('message')
      })

      var ws

      function connect() {
        console.log('connecting')
        connection.innerHTML = 'connecting...'
        ws = new WebSocket('ws://localhost:2999')
        ws.addEventListener('open', wsOpenEvent)
        ws.addEventListener('close', wsCloseEvent)
        ws.addEventListener('message', wsMessageEvent)
        ws.addEventListener('error', wsErrorEvent)
      }

      function wsOpenEvent(e) {
        console.log('connected')
        connection.innerHTML = 'connected'
      }

      function wsCloseEvent(e) {
        console.log('close')
        connection.innerHTML = 'disconnected'
        setTimeout(() => connect(), 5000)
      }

      function wsMessageEvent(e) {
        console.log('message', e)
      }

      function wsErrorEvent(e) {
        console.log('error', e)
      }

      connect()

    </script>
</body>

</html>


package.json
{
  "name": "web_socket",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "express": "^4.16.3",
    "ws": "^6.0.0"
  },
  "scripts": {
    "start": "node server.js"
  }
}


я так сделал reconnect )
и модули бы делал через webpack или parcel )

Роман Андреевич 19.09.2018 04:32

SuperZen, по сути то же самое, но только Реконнект делает через 5 секунд. Я так тоже сделал сначала)))) но теперь вопрос не в Реконнекте, а в том что контекст потерялся и при вызове из другого места ошибка

Роман Андреевич 19.09.2018 06:46

SuperZen, можно по идее сделать и без проверки доступности сервера, но тогда при создании нового экземпляра будет ошибка в консоли и все. Оборвать попытки, например, через 30 секунд и выдать клиенту сообщение какое нибудь, что серверу кранты. Вот.

У меня задача стоит, сделать коннект по сокет соединению, если обрыв то реконнект. Обязательно что бы модульная система была. Дабы коллеги вникали сразу, что бы использовать можно было в разных модулях.

Роман Андреевич 19.09.2018 06:49

Реконнект сделал, работает отлично. А вызывать не могу в других местах))))))))))))))))))))))

Роман Андреевич 19.09.2018 08:43

Коллеги, прошу опять помощи, как и писал выше после создания соединения, не могу вызывать sendMessage!!! как исправить????

SuperZen 19.09.2018 08:50

ну выложи куда-нибудь проект, а то, из 4 "классов" показал только 2, как происходит инициализация и т.д. неизвестно

Роман Андреевич 19.09.2018 09:01

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>

Роман Андреевич 19.09.2018 09:16

this теряется когда вызываю checkServer в socketModule. Вернее я его сохраняю в _t а в this.socket самого модуля он не сохраняется.

Но тогда почему если сделать console.log(this); и console.log(this.socket); в методе sendMessage первое выведет socketModule в котором будет this.socket = экземпляру websocket (все правильно), а второе выведет undefined

SuperZen 19.09.2018 11:31

const chat = new Chat;

не? https://developer.mozilla.org/ru/doc.../Operators/new
const chat = new Chat();

Malleys 19.09.2018 11:33

Та и не нашёл, где там модули! То, что вы запихнули файлы в папку `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)

Роман Андреевич 19.09.2018 11:44

Malleys, +100500 к вашей карме))))))))) Щас посмотрим!!!!!

Роман Андреевич 19.09.2018 11:54

Malleys, про автомагию это потому что толковых учебных пособий нету, где все и вся будет рассказано)))))))))))))))))))) поэтому приходится учиться как получается к сожалению

Malleys 19.09.2018 12:39

А авторы учебников откуда узнают?

Я не знаю как такое для обучения, но я уже прочитал спецификацию языка. Девятое издание. Большая часть конечно же взята из предыдущего издания. https://www.ecma-international.org/e...9.0/index.html

Я не знаю как такое для обучения, но что есть в JavaScript`е и как работает, всё описано. Я не говорю, что вам именно так надо изучать, просто я так узнаю.

Роман Андреевич 19.09.2018 12:47

Malleys, теперь по коду, который вы написали. Большое спасибо за помощь. Но!

в chat.js в конструкторе, после слушателя просто вызываем метод sendMessage и он не срабатывает!

Роман Андреевич 19.09.2018 12:48

те если просто вызвать в любом месте этот метод работать не будет если с задержкой то все нормально.

Malleys 19.09.2018 14:10

Цитата:

Сообщение от Роман Андреевич
в chat.js в конструкторе, после слушателя просто вызываем метод sendMessage и он не срабатывает!

Оно всё-таки работает, я допечатал немного, чтобы выводило в чат. Он выводит в чат, т. е. срабатывает sendMessage. И в текстовое поле, если напечатать то же срабатывает. Посмотрите код выше ещё раз.

Роман Андреевич 19.09.2018 14:16

Malleys, большое спасибо, разобрался))))) Я сам запутался. Еще раз спасибо

Роман Андреевич 19.09.2018 14:17

Malleys, все работает, теперь

Роман Андреевич 19.09.2018 14:37

Malleys, и кстати, а почему мои классы глобальные??? Насколько я понимаю, я добавляю свойства в объект window


Часовой пояс GMT +3, время: 16:20.