mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-21 04:35:49 +00:00
[TASK] emit connected and disconnected events from api
This commit is contained in:
@@ -61,6 +61,8 @@
|
|||||||
- [API Events](#api-events)
|
- [API Events](#api-events)
|
||||||
- [ledger](#ledger)
|
- [ledger](#ledger)
|
||||||
- [error](#error)
|
- [error](#error)
|
||||||
|
- [connected](#connected)
|
||||||
|
- [disconnected](#disconnected)
|
||||||
|
|
||||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
|
|
||||||
@@ -90,6 +92,14 @@ const api = new RippleAPI({
|
|||||||
api.on('error', (errorCode, errorMessage) => {
|
api.on('error', (errorCode, errorMessage) => {
|
||||||
console.log(errorCode + ': ' + errorMessage);
|
console.log(errorCode + ': ' + errorMessage);
|
||||||
});
|
});
|
||||||
|
api.on('connected', () => {
|
||||||
|
console.log('connected');
|
||||||
|
});
|
||||||
|
api.on('disconnected', (code) => {
|
||||||
|
// code - [close code](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent) sent by the server
|
||||||
|
// will be 1000 if this was normal closure
|
||||||
|
console.log('disconnected, code:', code);
|
||||||
|
});
|
||||||
api.connect().then(() => {
|
api.connect().then(() => {
|
||||||
/* insert code here */
|
/* insert code here */
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
@@ -3593,3 +3603,35 @@ api.on('error', (errorCode, errorMessage, data) => {
|
|||||||
tooBusy: The server is too busy to help you now.
|
tooBusy: The server is too busy to help you now.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## connected
|
||||||
|
|
||||||
|
This event is emitted after connection successfully opened.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
api.on('connected', () => {
|
||||||
|
console.log('Connection is open now.');
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## disconnected
|
||||||
|
|
||||||
|
This event is emitted when connection is closed.
|
||||||
|
|
||||||
|
### Return Value
|
||||||
|
|
||||||
|
The only parameter is a number containing the [close code](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent) send by the server.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
api.on('disconnected', (code) => {
|
||||||
|
if (code !== 1000) {
|
||||||
|
console.log('Connection is closed due to error.');
|
||||||
|
} else {
|
||||||
|
console.log('Connection is closed normally.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,14 @@ const api = new RippleAPI({
|
|||||||
api.on('error', (errorCode, errorMessage) => {
|
api.on('error', (errorCode, errorMessage) => {
|
||||||
console.log(errorCode + ': ' + errorMessage);
|
console.log(errorCode + ': ' + errorMessage);
|
||||||
});
|
});
|
||||||
|
api.on('connected', () => {
|
||||||
|
console.log('connected');
|
||||||
|
});
|
||||||
|
api.on('disconnected', (code) => {
|
||||||
|
// code - [close code](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent) sent by the server
|
||||||
|
// will be 1000 if this was normal closure
|
||||||
|
console.log('disconnected, code:', code);
|
||||||
|
});
|
||||||
api.connect().then(() => {
|
api.connect().then(() => {
|
||||||
/* insert code here */
|
/* insert code here */
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
|||||||
@@ -47,3 +47,35 @@ api.on('error', (errorCode, errorMessage, data) => {
|
|||||||
```
|
```
|
||||||
tooBusy: The server is too busy to help you now.
|
tooBusy: The server is too busy to help you now.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## connected
|
||||||
|
|
||||||
|
This event is emitted after connection successfully opened.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
api.on('connected', () => {
|
||||||
|
console.log('Connection is open now.');
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## disconnected
|
||||||
|
|
||||||
|
This event is emitted when connection is closed.
|
||||||
|
|
||||||
|
### Return Value
|
||||||
|
|
||||||
|
The only parameter is a number containing the [close code](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent) send by the server.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
api.on('disconnected', (code) => {
|
||||||
|
if (code !== 1000) {
|
||||||
|
console.log('Connection is closed due to error.');
|
||||||
|
} else {
|
||||||
|
console.log('Connection is closed normally.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
'use strict';
|
'use strict'; // eslint-disable-line
|
||||||
|
|
||||||
/* eslint-disable max-len */
|
/* eslint-disable max-len */
|
||||||
// Enable core-js polyfills. This allows use of ES6/7 extensions listed here:
|
// Enable core-js polyfills. This allows use of ES6/7 extensions listed here:
|
||||||
@@ -89,6 +89,12 @@ class RippleAPI extends EventEmitter {
|
|||||||
this.connection.on('error', (errorCode, errorMessage, data) => {
|
this.connection.on('error', (errorCode, errorMessage, data) => {
|
||||||
this.emit('error', errorCode, errorMessage, data);
|
this.emit('error', errorCode, errorMessage, data);
|
||||||
});
|
});
|
||||||
|
this.connection.on('connected', () => {
|
||||||
|
this.emit('connected');
|
||||||
|
});
|
||||||
|
this.connection.on('disconnected', onError => {
|
||||||
|
this.emit('disconnected', onError);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// use null object pattern to provide better error message if user
|
// use null object pattern to provide better error message if user
|
||||||
// tries to call a method that requires a connection
|
// tries to call a method that requires a connection
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
'use strict'; // eslint-disable-line
|
||||||
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const {EventEmitter} = require('events');
|
const {EventEmitter} = require('events');
|
||||||
const WebSocket = require('ws');
|
const WebSocket = require('ws');
|
||||||
@@ -97,36 +99,42 @@ class Connection extends EventEmitter {
|
|||||||
return this._state === WebSocket.OPEN && this._isReady;
|
return this._state === WebSocket.OPEN && this._isReady;
|
||||||
}
|
}
|
||||||
|
|
||||||
_onUnexpectedClose(resolve, reject) {
|
_onUnexpectedClose(beforeOpen, resolve, reject, code) {
|
||||||
if (this._onOpenErrorBound) {
|
if (this._onOpenErrorBound) {
|
||||||
this._ws.removeListener('error', this._onOpenErrorBound);
|
this._ws.removeListener('error', this._onOpenErrorBound);
|
||||||
this._onOpenErrorBound = null;
|
this._onOpenErrorBound = null;
|
||||||
}
|
}
|
||||||
this._ws = null;
|
this._ws = null;
|
||||||
this._isReady = false;
|
this._isReady = false;
|
||||||
if (_.isFunction(resolve)) {
|
if (beforeOpen) {
|
||||||
// connection was closed before it was properly opened, so we must return
|
// connection was closed before it was properly opened, so we must return
|
||||||
// error to connect's caller
|
// error to connect's caller
|
||||||
this.connect().then(resolve, reject);
|
this.connect().then(resolve, reject);
|
||||||
} else {
|
} else {
|
||||||
this.emit('disconnected', true);
|
// if first parameter ws lib sends close code,
|
||||||
|
// but sometimes it forgots about it, so default to 1006 - CLOSE_ABNORMAL
|
||||||
|
this.emit('disconnected', code || 1006);
|
||||||
this._retryConnect();
|
this._retryConnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_retryConnect() {
|
_calculateTimeout(retriesCount) {
|
||||||
this._retry += 1;
|
return (retriesCount < 40)
|
||||||
const retryTimeout = (this._retry < 40)
|
|
||||||
// First, for 2 seconds: 20 times per second
|
// First, for 2 seconds: 20 times per second
|
||||||
? (1000 / 20)
|
? (1000 / 20)
|
||||||
: (this._retry < 40 + 60)
|
: (retriesCount < 40 + 60)
|
||||||
// Then, for 1 minute: once per second
|
// Then, for 1 minute: once per second
|
||||||
? (1000)
|
? (1000)
|
||||||
: (this._retry < 40 + 60 + 60)
|
: (retriesCount < 40 + 60 + 60)
|
||||||
// Then, for 10 minutes: once every 10 seconds
|
// Then, for 10 minutes: once every 10 seconds
|
||||||
? (10 * 1000)
|
? (10 * 1000)
|
||||||
// Then: once every 30 seconds
|
// Then: once every 30 seconds
|
||||||
: (30 * 1000);
|
: (30 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
_retryConnect() {
|
||||||
|
this._retry += 1;
|
||||||
|
const retryTimeout = this._calculateTimeout(this._retry);
|
||||||
this._retryTimer = setTimeout(() => {
|
this._retryTimer = setTimeout(() => {
|
||||||
this.connect().catch(this._retryConnect.bind(this));
|
this.connect().catch(this._retryConnect.bind(this));
|
||||||
}, retryTimeout);
|
}, retryTimeout);
|
||||||
@@ -139,7 +147,8 @@ class Connection extends EventEmitter {
|
|||||||
|
|
||||||
_onOpen() {
|
_onOpen() {
|
||||||
this._ws.removeListener('close', this._onUnexpectedCloseBound);
|
this._ws.removeListener('close', this._onUnexpectedCloseBound);
|
||||||
this._onUnexpectedCloseBound = this._onUnexpectedClose.bind(this);
|
this._onUnexpectedCloseBound =
|
||||||
|
this._onUnexpectedClose.bind(this, false, null, null);
|
||||||
this._ws.once('close', this._onUnexpectedCloseBound);
|
this._ws.once('close', this._onUnexpectedCloseBound);
|
||||||
|
|
||||||
this._ws.removeListener('error', this._onOpenErrorBound);
|
this._ws.removeListener('error', this._onOpenErrorBound);
|
||||||
@@ -234,7 +243,7 @@ class Connection extends EventEmitter {
|
|||||||
// resolve connect's promise after reconnect in that case.
|
// resolve connect's promise after reconnect in that case.
|
||||||
// after open event we will rebound _onUnexpectedCloseBound
|
// after open event we will rebound _onUnexpectedCloseBound
|
||||||
// without resolve and reject functions
|
// without resolve and reject functions
|
||||||
this._onUnexpectedCloseBound = this._onUnexpectedClose.bind(this,
|
this._onUnexpectedCloseBound = this._onUnexpectedClose.bind(this, true,
|
||||||
resolve, reject);
|
resolve, reject);
|
||||||
this._ws.once('close', this._onUnexpectedCloseBound);
|
this._ws.once('close', this._onUnexpectedCloseBound);
|
||||||
this._ws.once('open', () => this._onOpen().then(resolve, reject));
|
this._ws.once('open', () => this._onOpen().then(resolve, reject));
|
||||||
@@ -252,10 +261,10 @@ class Connection extends EventEmitter {
|
|||||||
this._ws.once('close', resolve);
|
this._ws.once('close', resolve);
|
||||||
} else {
|
} else {
|
||||||
this._ws.removeListener('close', this._onUnexpectedCloseBound);
|
this._ws.removeListener('close', this._onUnexpectedCloseBound);
|
||||||
this._ws.once('close', () => {
|
this._ws.once('close', code => {
|
||||||
this._ws = null;
|
this._ws = null;
|
||||||
this._isReady = false;
|
this._isReady = false;
|
||||||
this.emit('disconnected', false);
|
this.emit('disconnected', code || 1000); // 1000 - CLOSE_NORMAL
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
this._ws.close();
|
this._ws.close();
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
'use strict'; // eslint-disable-line
|
||||||
/* eslint-disable max-nested-callbacks */
|
/* eslint-disable max-nested-callbacks */
|
||||||
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
@@ -212,7 +213,9 @@ describe('Connection', function() {
|
|||||||
|
|
||||||
let connectsCount = 0;
|
let connectsCount = 0;
|
||||||
let disconnectsCount = 0;
|
let disconnectsCount = 0;
|
||||||
this.api.connection.on('disconnected', () => {
|
let code = 0;
|
||||||
|
this.api.connection.on('disconnected', _code => {
|
||||||
|
code = _code;
|
||||||
disconnectsCount += 1;
|
disconnectsCount += 1;
|
||||||
});
|
});
|
||||||
this.api.connection.on('connected', () => {
|
this.api.connection.on('connected', () => {
|
||||||
@@ -224,6 +227,9 @@ describe('Connection', function() {
|
|||||||
if (disconnectsCount !== 3) {
|
if (disconnectsCount !== 3) {
|
||||||
done(new Error('disconnectsCount must be equal to 3 (got ' +
|
done(new Error('disconnectsCount must be equal to 3 (got ' +
|
||||||
disconnectsCount + ' instead)'));
|
disconnectsCount + ' instead)'));
|
||||||
|
} else if (code !== 1006) {
|
||||||
|
done(new Error('disconnect must send code 1006 (got ' + code +
|
||||||
|
' instead)'));
|
||||||
} else {
|
} else {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
@@ -233,6 +239,36 @@ describe('Connection', function() {
|
|||||||
breakConnection();
|
breakConnection();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should emit disconnected event with code 1000 (CLOSE_NORMAL)',
|
||||||
|
function(done
|
||||||
|
) {
|
||||||
|
this.api.once('disconnected', code => {
|
||||||
|
assert.strictEqual(code, 1000);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
this.api.disconnect();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit disconnected event with code 1006 (CLOSE_ABNORMAL)',
|
||||||
|
function(done
|
||||||
|
) {
|
||||||
|
if (process.browser) {
|
||||||
|
// can't be tested in browser this way, so skipping
|
||||||
|
done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.api.once('disconnected', code => {
|
||||||
|
assert.strictEqual(code, 1006);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
this.mockRippled.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit connected event on after reconnect', function(done) {
|
||||||
|
this.api.once('connected', done);
|
||||||
|
this.api.connection._ws.close();
|
||||||
|
});
|
||||||
|
|
||||||
it('Multiply connect calls', function() {
|
it('Multiply connect calls', function() {
|
||||||
return this.api.connect().then(() => {
|
return this.api.connect().then(() => {
|
||||||
return this.api.connect();
|
return this.api.connect();
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
'use strict'; // eslint-disable-line
|
||||||
|
|
||||||
const net = require('net');
|
const net = require('net');
|
||||||
const RippleAPI = require('ripple-api').RippleAPI;
|
const RippleAPI = require('ripple-api').RippleAPI;
|
||||||
const RippleAPIBroadcast = require('ripple-api').RippleAPIBroadcast;
|
const RippleAPIBroadcast = require('ripple-api').RippleAPIBroadcast;
|
||||||
|
|||||||
Reference in New Issue
Block a user