backendless-rt-client
Version:
Backendless RT Client for connect to Backendless RT Server
258 lines (211 loc) • 5.55 kB
JavaScript
import RTListeners from './listeners'
const ListenerTypes = {
CONNECT : 'CONNECT',
ERROR : 'ERROR',
COMMAND : 'COMMAND',
USER_STATUS: 'USER_STATUS',
}
export default class RTScopeConnector extends RTListeners {
/**
* @static
* @function
* @decorator
* @param {Boolean} [returnPromise] - if passed to TRUE the method returns a Promise
* and will be resolved when the instance is connected to scope
* and method return any result
*
* decorate instance's methods of the Class
* puts the method's execution to pool and run it immediately after connected to Connection Scope.
* if the instance is already connected to the scope the method will be executed immediately
**/
static connectionRequired = connectionRequired
/**
* @abstract getter, must be overridden in an inherited class
* must returns a function for adding subscriptions to CONNECT to connection scope
* For ex.: RTProvider.subscriptions.connectToRSO
**/
get connectSubscriber() {
return null
}
/**
* @abstract getter, must be overridden in an inherited class
*
* must returns a function for adding subscriptions to listening COMMANDS in connection scope
* For ex.: RTProvider.subscriptions.onRSOCommand
**/
get commandSubscriber() {
return null
}
/**
* @abstract getter, must be overridden in an inherited class
*
* must returns a function for adding subscriptions to listening changes of USER_STATUS in connection scope
* For ex.: RTProvider.subscriptions.onRSOUserStatus
**/
get usersSubscriber() {
return null
}
/**
* @abstract getter, must be overridden in an inherited class
*
* must returns a function for sending COMMAND into connection scope
* For ex.: RTProvider.methods.sendRSOCommand
**/
get commandSender() {
return null
}
constructor(options) {
super()
this.options = options
this.waitConnection = []
this.connect()
}
/**
* @public method
*
* connect to connection scope, if you already connected the method do nothing
**/
connect() {
if (!this.isConnected()) {
this.connection = this.connectSubscriber(this.getScopeOptions(), {
onError: error => this.onError(error),
onReady: () => this.onConnect(),
onStop : () => this.onDisconnect()
})
}
}
/**
* @public method
*
* disconnect from connection scope, if you already disconnect the method do nothing
**/
disconnect() {
if (this.isConnected()) {
this.connection.stop()
}
}
/**
* @public method
*
* returns TRUE if you connected to connection scope otherwise returns FALSE
**/
isConnected() {
return !!this.connection && this.connection.isReady()
}
/**
* @private method
**/
getSubscriptionOptions() {
return this.getScopeOptions()
}
/**
* @private method
**/
getScopeOptions() {
return this.options
}
/**
* @private method
**/
onConnect() {
this.waitConnection.forEach(operation => operation())
this.waitConnection = []
this.runSimpleListeners(ListenerTypes.CONNECT)
}
/**
* @private method
**/
onError(error) {
this.runSimpleListeners(ListenerTypes.ERROR, error)
}
/**
* @private method
**/
onDisconnect() {
this.connection = null
}
/**
* @public method
**/
removeAllListeners() {
this.waitConnection = []
super.removeAllListeners()
return this
}
/**
* @public method
**/
addConnectListener(callback, onError) {
this.addSimpleListener(ListenerTypes.CONNECT, callback)
if (onError) {
this.addSimpleListener(ListenerTypes.ERROR, onError)
}
return this
}
/**
* @public method
**/
removeConnectListeners(callback, onError) {
this.removeSimpleListener(ListenerTypes.CONNECT, callback)
if (onError) {
this.removeSimpleListener(ListenerTypes.ERROR, onError)
}
return this
}
/**
* @public method
**/
addCommandListener(callback, onError) {
this.addSubscription(ListenerTypes.COMMAND, this.commandSubscriber, { callback, onError })
return this
}
/**
* @public method
**/
removeCommandListeners(callback) {
this.stopSubscription(ListenerTypes.COMMAND, { callback })
return this
}
/**
* @public method
**/
addUserStatusListener(callback, onError) {
this.addSubscription(ListenerTypes.USER_STATUS, this.usersSubscriber, { callback, onError })
return this
}
/**
* @public method
**/
removeUserStatusListeners(callback) {
this.stopSubscription(ListenerTypes.USER_STATUS, { callback })
return this
}
/**
* @public method
**/
send(type, data) {
return this.commandSender({ ...this.getScopeOptions(), type, data })
}
}
function connectionRequired(returnPromise) {
return function (target, key, descriptor) {
const decorated = descriptor.value
descriptor.value = function () {
const run = () => decorated.apply(this, arguments)
if (this.isConnected()) {
return run()
}
if (returnPromise) {
return new Promise((resolve, reject) => this.waitConnection.push(() => run().then(resolve, reject)))
}
this.waitConnection.push(run)
return this
}
return descriptor
}
}