pandora-hub
Version:
pandora.js messenge hub
181 lines (156 loc) • 4.8 kB
text/typescript
import {ConsumerExtInfo, Introspection, ObjectDescription, ReplyPackage, Selector} from '../domain';
import {HubClient} from '../hub/HubClient';
import {
OBJECT_ACTION_GET_PROPERTY, OBJECT_ACTION_INTROSPECT, OBJECT_ACTION_INVOKE,
OBJECT_ACTION_SUBSCRIBE, OBJECT_ACTION_UNSUBSCRIBE
} from '../const';
import {DefaultObjectProxy} from './DefaultObjectProxy';
import {ProviderManager} from './ProviderManager';
import EventEmitter = require('events');
export class ObjectConsumer extends EventEmitter {
public objectDescription: ObjectDescription;
private hubClient: HubClient;
private providerManager: ProviderManager;
private objectProxy: DefaultObjectProxy;
private timeout: number;
constructor(objectDescription: ObjectDescription, hubClient, providerManager: ProviderManager, extInfo?: ConsumerExtInfo) {
super();
this.objectDescription = objectDescription;
this.hubClient = hubClient;
this.providerManager = providerManager;
if(extInfo) {
this.timeout = extInfo.timeout;
}
}
/**
* Invoke a method from Remote Object
* @param {string} method
* @param {any[]} params
* @return {Promise<any>}
*/
public async invoke(method: string, params: any[]): Promise<any> {
const res = await this.hubClient.invoke({
objectName: this.objectDescription.name,
objectTag: this.objectDescription.tag,
}, OBJECT_ACTION_INVOKE, {
timeout: this.timeout,
propertyName: method,
data: params
});
if(res.error) {
throw res.error;
}
return res.data;
}
/**
* Invoke a method from Remote Object
* @param {string} method
* @param {any[]} params
* @return {Promise<any>}
*/
public async multipleInvoke(method: string, params: any[], selectors?: Selector): Promise<ReplyPackage[]> {
const res = await this.hubClient.multipleInvoke({
objectName: this.objectDescription.name,
objectTag: this.objectDescription.tag,
...(selectors || {})
}, OBJECT_ACTION_INVOKE, {
timeout: this.timeout,
propertyName: method,
data: params
});
return res;
}
/**
* Get a property from Remote Object
* @param {string} name
* @return {Promise<any>}
*/
public async getProperty(name: string) {
const res = await this.hubClient.invoke({
objectName: this.objectDescription.name,
objectTag: this.objectDescription.tag
}, OBJECT_ACTION_GET_PROPERTY, {
timeout: this.timeout,
propertyName: name
});
if(res.error) {
throw res.error;
}
return res.data;
}
private subscriberPublished = false;
public async subscribe(register: string, fn) {
const cnt = this.listenerCount(register);
this.addListener(register, fn);
if(!this.subscriberPublished) {
this.subscriberPublished = true;
await this.providerManager.publish({
callback: (register: string, params: any[]) => {
this.emit(register, ...params);
}
}, {
...this.objectDescription,
name: this.objectDescription.name + '@subscriber'
});
}
if(cnt === 0) {
const res = await this.hubClient.invoke({
objectName: this.objectDescription.name,
objectTag: this.objectDescription.tag,
}, OBJECT_ACTION_SUBSCRIBE, {
timeout: this.timeout,
register: register
});
if(res.error) {
throw res.error;
}
return res.data;
}
}
public async unsubscribe(register: string, fn?) {
if (fn) {
this.removeListener(register, fn);
} else {
this.removeAllListeners(register);
}
if(this.listenerCount(register) === 0) {
const res = await this.hubClient.invoke({
objectName: this.objectDescription.name,
objectTag: this.objectDescription.tag,
}, OBJECT_ACTION_UNSUBSCRIBE, {
timeout: this.timeout,
register: register
});
if(res.error) {
throw res.error;
}
return res.data;
}
}
/**
* Get Introspection from Remote Object
* @return {Promise<Introspection>}
*/
public async introspect(): Promise<Introspection> {
const res = await this.hubClient.invoke({
objectName: this.objectDescription.name,
objectTag: this.objectDescription.tag
}, OBJECT_ACTION_INTROSPECT, null);
if(res.error) {
throw res.error;
}
return res.data;
}
/**
* Get Object Proxy
* @return {Promise<T & DefaultObjectProxy>}
*/
public async getProxy<T extends any>(): Promise<T & DefaultObjectProxy> {
if(this.objectProxy) {
return <any> this.objectProxy;
}
const introspection = await this.introspect();
this.objectProxy = new DefaultObjectProxy(this, introspection);
return <any> this.objectProxy;
}
}