mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-18 12:52:42 +01:00
Implement JX.WebSocket
Summary: Ref T6559. Wraps WebSocket in a reasonable driver class which does event dispatch, some state management, and handles automatic reconnect. Test Plan: In Safari, Firefox and Chrome, connected to a websocket server and sent messages back and forth. Terminated and restarted server, saw automatic reconnects successfully reestablish a connection on all browsers. Reviewers: btrahan, joshuaspence Reviewed By: joshuaspence Subscribers: epriestley Maniphest Tasks: T6559 Differential Revision: https://secure.phabricator.com/D11252
This commit is contained in:
parent
6de8fe418c
commit
8c21ef2c0b
2 changed files with 183 additions and 0 deletions
|
@ -200,6 +200,7 @@ return array(
|
|||
'rsrc/externals/javelin/lib/Router.js' => '29274e2b',
|
||||
'rsrc/externals/javelin/lib/URI.js' => '6eff08aa',
|
||||
'rsrc/externals/javelin/lib/Vector.js' => 'cc1bd0b0',
|
||||
'rsrc/externals/javelin/lib/WebSocket.js' => '897b80bf',
|
||||
'rsrc/externals/javelin/lib/Workflow.js' => 'd149e002',
|
||||
'rsrc/externals/javelin/lib/__tests__/Cookie.js' => '5ed109e8',
|
||||
'rsrc/externals/javelin/lib/__tests__/DOM.js' => 'c984504b',
|
||||
|
@ -685,6 +686,7 @@ return array(
|
|||
'javelin-view-interpreter' => '0c33c1a0',
|
||||
'javelin-view-renderer' => '6c2b09a2',
|
||||
'javelin-view-visitor' => 'efe49472',
|
||||
'javelin-websocket' => '897b80bf',
|
||||
'javelin-workflow' => 'd149e002',
|
||||
'lightbox-attachment-css' => '7acac05d',
|
||||
'maniphest-batch-editor' => '8f380ebc',
|
||||
|
@ -1360,6 +1362,9 @@ return array(
|
|||
'javelin-view-interpreter',
|
||||
'javelin-view-renderer',
|
||||
),
|
||||
'897b80bf' => array(
|
||||
'javelin-install',
|
||||
),
|
||||
'8a41885b' => array(
|
||||
'javelin-install',
|
||||
'javelin-dom',
|
||||
|
|
178
webroot/rsrc/externals/javelin/lib/WebSocket.js
vendored
Normal file
178
webroot/rsrc/externals/javelin/lib/WebSocket.js
vendored
Normal file
|
@ -0,0 +1,178 @@
|
|||
/**
|
||||
* @requires javelin-install
|
||||
* @provides javelin-websocket
|
||||
* @javelin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Wraps a WebSocket.
|
||||
*/
|
||||
JX.install('WebSocket', {
|
||||
|
||||
construct: function(uri) {
|
||||
this.setURI(uri);
|
||||
},
|
||||
|
||||
properties: {
|
||||
URI: null,
|
||||
|
||||
/**
|
||||
* Called when a connection is established or re-established after an
|
||||
* interruption.
|
||||
*/
|
||||
openHandler: null,
|
||||
|
||||
/**
|
||||
* Called when a message is received.
|
||||
*/
|
||||
messageHandler: null,
|
||||
|
||||
/**
|
||||
* Called when the connection is closed.
|
||||
*
|
||||
* You can return `true` to prevent the socket from reconnecting.
|
||||
*/
|
||||
closeHandler: null
|
||||
},
|
||||
|
||||
members: {
|
||||
/**
|
||||
* The underlying WebSocket.
|
||||
*/
|
||||
_socket: null,
|
||||
|
||||
/**
|
||||
* Is the socket connected?
|
||||
*/
|
||||
_isOpen: false,
|
||||
|
||||
/**
|
||||
* Has the caller asked us to close?
|
||||
*
|
||||
* By default, we reconnect when the connection is interrupted.
|
||||
* This stops us from reconnecting if @{method:close} was called.
|
||||
*/
|
||||
_shouldClose: false,
|
||||
|
||||
/**
|
||||
* Number of milliseconds to wait after a connection failure before
|
||||
* attempting to reconnect.
|
||||
*/
|
||||
_delayUntilReconnect: null,
|
||||
|
||||
|
||||
/**
|
||||
* Open the connection.
|
||||
*/
|
||||
open: function() {
|
||||
if (!window.WebSocket) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._shouldClose = false;
|
||||
this._resetDelay();
|
||||
|
||||
this._socket = new WebSocket(this.getURI());
|
||||
this._socket.onopen = JX.bind(this, this._onopen);
|
||||
this._socket.onmessage = JX.bind(this, this._onmessage);
|
||||
this._socket.onclose = JX.bind(this, this._onclose);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Send a message.
|
||||
*
|
||||
* If the connection is not currently open, this method has no effect and
|
||||
* the messages vanishes into the ether.
|
||||
*/
|
||||
send: function(message) {
|
||||
if (this._isOpen) {
|
||||
this._socket.send(message);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Close the connection.
|
||||
*/
|
||||
close: function() {
|
||||
if (!$this._isOpen) {
|
||||
return;
|
||||
}
|
||||
this._shouldClose = true;
|
||||
this._socket.close();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Callback for connection open.
|
||||
*/
|
||||
_onopen: function(e) {
|
||||
this._isOpen = true;
|
||||
|
||||
// Reset the reconnect delay, since we connected successfully.
|
||||
this._resetDelay();
|
||||
|
||||
var handler = this.getOpenHandler();
|
||||
if (handler) {
|
||||
handler();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Reset the reconnect delay to its base value.
|
||||
*/
|
||||
_resetDelay: function() {
|
||||
this._delayUntilReconnect = 2000;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Callback for message received.
|
||||
*/
|
||||
_onmessage: function(e) {
|
||||
var data = e.data;
|
||||
|
||||
var handler = this.getMessageHandler();
|
||||
if (handler) {
|
||||
handler(data);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Callback for connection close.
|
||||
*/
|
||||
_onclose: function(e) {
|
||||
this._isOpen = false;
|
||||
|
||||
var done = false;
|
||||
|
||||
var handler = this.getCloseHandler();
|
||||
if (handler) {
|
||||
done = handler();
|
||||
}
|
||||
|
||||
// If we didn't explicitly see a close() call and the close handler
|
||||
// did not return `true` to stop the reconnect, wait a little while
|
||||
// and try to reconnect.
|
||||
if (!done && !this._shouldClose) {
|
||||
setTimeout(JX.bind(this, this._reconnect), this._delayUntilReconnect);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Reconnect an interrupted socket.
|
||||
*/
|
||||
_reconnect: function() {
|
||||
// Increase the reconnect delay by a factor of 2. If we fail to open the
|
||||
// connection, the close handler will send us back here. We'll reconnect
|
||||
// more and more slowly until we eventually get a valid connection.
|
||||
this._delayUntilReconnect = this._delayUntilReconnect * 2;
|
||||
this.open();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
Loading…
Reference in a new issue