2020-09-10 16:21:01 +00:00
|
|
|
import { generateId } from '../helpers/idMethods';
|
|
|
|
|
2020-09-11 07:59:23 +00:00
|
|
|
/**
|
|
|
|
* A Layer to communicate.
|
|
|
|
*
|
|
|
|
* @export
|
|
|
|
* @interface ICommunicationInterface
|
|
|
|
*/
|
2020-08-21 16:38:21 +00:00
|
|
|
export interface ICommunicationInterface {
|
2020-09-11 07:59:23 +00:00
|
|
|
/**
|
|
|
|
* Function used to subscribe to updates. If there exist
|
|
|
|
* some state change in the Communication Interface it should
|
|
|
|
* be provided on the registered functions
|
|
|
|
*
|
2020-09-12 00:59:30 +00:00
|
|
|
* @param {string} event The Selected Event.
|
2020-09-11 07:59:23 +00:00
|
|
|
* @param {(...args) => void} cb The Callback, which will be called if an Event occours
|
|
|
|
* @memberof ICommunicationInterface
|
|
|
|
*/
|
2020-09-12 00:59:30 +00:00
|
|
|
on(event: string, cb: (...args) => void);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function used to unsubscribe from updates
|
|
|
|
*
|
|
|
|
* @param {string} event The Selected Event.
|
|
|
|
* @param {(...args) => void} cb The Callback, which should be unsubscribed.
|
|
|
|
* @memberof ICommunicationInterface
|
|
|
|
*/
|
|
|
|
off(event: string, cb: (...args) => void);
|
|
|
|
|
2020-09-11 07:59:23 +00:00
|
|
|
/**
|
|
|
|
* Function to send data via the Communication interface
|
|
|
|
*
|
2020-09-12 00:59:30 +00:00
|
|
|
* @param {string} topic The Topic, on which data will be published
|
2020-09-11 07:59:23 +00:00
|
|
|
* @param {*} data The data. Could be any type and element. In Generel it should be parsable.
|
|
|
|
* @memberof ICommunicationInterface
|
|
|
|
*/
|
2020-09-12 00:59:30 +00:00
|
|
|
send(topic: string, data): void;
|
2020-08-21 16:38:21 +00:00
|
|
|
}
|
|
|
|
|
2020-09-12 00:59:30 +00:00
|
|
|
export type requestTask = {
|
2020-08-21 16:38:21 +00:00
|
|
|
type: 'request',
|
|
|
|
taskId: number,
|
2020-09-12 00:59:30 +00:00
|
|
|
functionId: string,
|
2020-08-21 16:38:21 +00:00
|
|
|
params: {
|
|
|
|
idx: number,
|
|
|
|
data: any
|
|
|
|
}[]
|
2020-09-12 00:59:30 +00:00
|
|
|
callbacks: ({
|
2020-08-21 16:38:21 +00:00
|
|
|
functionId: string,
|
|
|
|
idx: number,
|
2020-09-12 00:59:30 +00:00
|
|
|
deleteAfterCalling: boolean,
|
|
|
|
} & callOptions)[]
|
|
|
|
}
|
|
|
|
|
|
|
|
export type callOptions = {
|
|
|
|
deletableCallbacks: Array<number>;
|
|
|
|
noCallbackItegrated?: boolean;
|
|
|
|
noErrorTest?: boolean;
|
2020-08-21 16:38:21 +00:00
|
|
|
}
|
|
|
|
|
2020-09-12 00:59:30 +00:00
|
|
|
export type responseOfTask = {
|
2020-08-21 16:38:21 +00:00
|
|
|
type: 'response',
|
|
|
|
taskId: number,
|
|
|
|
result?: any,
|
|
|
|
error?: any
|
|
|
|
}
|
|
|
|
|
2020-09-12 00:59:30 +00:00
|
|
|
export type availableServices = {
|
|
|
|
dispatcher: string,
|
|
|
|
services: string[]
|
|
|
|
}
|
|
|
|
|
|
|
|
export type nopeDispatcherOptions = {
|
|
|
|
communicator: ICommunicationInterface,
|
|
|
|
subscriptionMode?: 'individual' | 'generic',
|
|
|
|
}
|
|
|
|
|
2020-08-21 16:38:21 +00:00
|
|
|
/**
|
2020-09-11 07:59:23 +00:00
|
|
|
* A Dispatcher to perform a function on a Remote
|
|
|
|
* Dispatcher. Therefore a Task is created and forwarded
|
|
|
|
* to the remote.
|
|
|
|
*
|
|
|
|
* @export
|
|
|
|
* @class nopeDispatcher
|
2020-08-21 16:38:21 +00:00
|
|
|
*/
|
2020-08-23 07:18:11 +00:00
|
|
|
export class nopeDispatcher {
|
2020-08-21 16:38:21 +00:00
|
|
|
|
2020-09-12 00:59:30 +00:00
|
|
|
public readonly id: string;
|
|
|
|
|
2020-09-11 07:59:23 +00:00
|
|
|
/**
|
|
|
|
* Internal Element to store the registered Functions
|
|
|
|
*
|
|
|
|
* @protected
|
|
|
|
* @memberof nopeDispatcher
|
|
|
|
*/
|
2020-09-12 00:59:30 +00:00
|
|
|
protected _definedFunctions: Map<string, (...args) => Promise<any>>;
|
|
|
|
protected _communicatorCallbacks: Map<string, (data) => any>;
|
|
|
|
protected _communicator: ICommunicationInterface
|
2020-09-11 07:59:23 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal Element to store the running tasks.
|
|
|
|
*
|
|
|
|
* @protected
|
|
|
|
* @memberof nopeDispatcher
|
|
|
|
*/
|
2020-08-21 16:38:21 +00:00
|
|
|
protected _runningTasks: Map<number, {
|
|
|
|
resolve: (value: any) => void;
|
|
|
|
reject: (error: any) => void;
|
|
|
|
}>;
|
|
|
|
|
2020-09-11 07:59:23 +00:00
|
|
|
/**
|
|
|
|
* Creates an instance of nopeDispatcher.
|
|
|
|
* @param {ICommunicationInterface} communicator The Communication Layer which should be used.
|
|
|
|
* @memberof nopeDispatcher
|
|
|
|
*/
|
2020-09-12 00:59:30 +00:00
|
|
|
constructor(public options: nopeDispatcherOptions) {
|
|
|
|
|
|
|
|
this._communicator = options.communicator;
|
|
|
|
|
|
|
|
this.options.subscriptionMode = this.options.subscriptionMode || 'generic';
|
|
|
|
|
|
|
|
this.id = generateId();
|
|
|
|
|
2020-08-21 16:38:21 +00:00
|
|
|
this.reset();
|
|
|
|
this.init();
|
|
|
|
}
|
|
|
|
|
2020-09-11 07:59:23 +00:00
|
|
|
/**
|
|
|
|
* Internal Method to handle some requests.
|
|
|
|
*
|
|
|
|
* @protected
|
|
|
|
* @param {requestTask} data The provided data of the request
|
2020-09-12 00:59:30 +00:00
|
|
|
* @param {*} [_function=this._definedFunctions.get(data.functionId)] The Function can be provided
|
2020-09-11 07:59:23 +00:00
|
|
|
* @return {Promise<void>}
|
|
|
|
* @memberof nopeDispatcher
|
|
|
|
*/
|
2020-09-12 00:59:30 +00:00
|
|
|
protected async _handleExternalRequest(data: requestTask, _function?: (...args) => Promise<any>): Promise<void> {
|
2020-08-21 16:38:21 +00:00
|
|
|
try {
|
2020-09-12 00:59:30 +00:00
|
|
|
|
|
|
|
// Try to get the function if not provided:
|
|
|
|
if (typeof _function !== 'function') {
|
|
|
|
_function = this._definedFunctions.get(data.functionId);
|
|
|
|
}
|
|
|
|
|
2020-08-21 16:38:21 +00:00
|
|
|
const _this = this;
|
2020-09-11 07:59:23 +00:00
|
|
|
|
2020-08-21 16:38:21 +00:00
|
|
|
if (typeof _function === 'function') {
|
2020-09-11 07:59:23 +00:00
|
|
|
// Only if the Function is present extract the arguments etc.
|
2020-08-21 16:38:21 +00:00
|
|
|
const args = [];
|
2020-09-11 07:59:23 +00:00
|
|
|
|
|
|
|
// First extract the basic arguments
|
2020-08-21 16:38:21 +00:00
|
|
|
data.params.map(item => args[item.idx] = item.data);
|
2020-09-11 07:59:23 +00:00
|
|
|
|
|
|
|
// Add the Callbacks. Therefore create a function which will
|
|
|
|
// trigger the remote.
|
2020-08-21 16:38:21 +00:00
|
|
|
data.callbacks.map(item => args[item.idx] = async (..._args) => {
|
2020-09-10 16:21:01 +00:00
|
|
|
return await _this.performCall(item.functionId, _args);
|
2020-08-21 16:38:21 +00:00
|
|
|
});
|
|
|
|
|
2020-09-11 07:59:23 +00:00
|
|
|
// Perform the Task it self.
|
2020-09-10 16:21:01 +00:00
|
|
|
const _result = await _function(...args);
|
|
|
|
|
2020-09-11 07:59:23 +00:00
|
|
|
// Define the Result message
|
2020-08-21 16:38:21 +00:00
|
|
|
const result: responseOfTask = {
|
2020-09-10 16:21:01 +00:00
|
|
|
result: typeof (_result) !== 'undefined' ? _result : null,
|
2020-08-21 16:38:21 +00:00
|
|
|
taskId: data.taskId,
|
|
|
|
type: 'response'
|
|
|
|
}
|
|
|
|
|
2020-09-11 07:59:23 +00:00
|
|
|
// Use the communicator to publish the event.
|
2020-09-12 00:59:30 +00:00
|
|
|
this._communicator.send('response', result);
|
2020-08-21 16:38:21 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
|
2020-09-11 07:59:23 +00:00
|
|
|
// An Error occourd => Forward the Error.
|
2020-08-21 16:38:21 +00:00
|
|
|
const result: responseOfTask = {
|
|
|
|
error,
|
|
|
|
taskId: data.taskId,
|
|
|
|
type: 'response'
|
|
|
|
}
|
|
|
|
|
2020-09-11 07:59:23 +00:00
|
|
|
// Send the Error via the communicator to the remote.
|
2020-09-12 00:59:30 +00:00
|
|
|
this._communicator.send('response', result);
|
2020-08-21 16:38:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-11 07:59:23 +00:00
|
|
|
/**
|
|
|
|
* Internal Function to handle responses. In Generale,
|
|
|
|
* the dispatcher checks if there is an open task with
|
|
|
|
* the provided id. If so => finish the promise.
|
|
|
|
*
|
|
|
|
* @protected
|
|
|
|
* @param {responseOfTask} data The Data provided to handle the Response.
|
|
|
|
* @return {void} Nothing
|
|
|
|
* @memberof nopeDispatcher
|
|
|
|
*/
|
|
|
|
protected _handleExternalResponse(data: responseOfTask): void {
|
2020-08-21 16:38:21 +00:00
|
|
|
try {
|
|
|
|
// Extract the Task
|
|
|
|
const task = this._runningTasks.get(data.taskId);
|
|
|
|
|
|
|
|
// Delete the Task:
|
|
|
|
this._runningTasks.delete(data.taskId);
|
|
|
|
|
|
|
|
// Based on the Result of the Remote =>
|
|
|
|
if (task && data.error) {
|
|
|
|
return task.reject(data.error);
|
|
|
|
}
|
2020-08-25 22:11:26 +00:00
|
|
|
if (task) {
|
2020-08-21 16:38:21 +00:00
|
|
|
return task.resolve(data.result);
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-11 07:59:23 +00:00
|
|
|
/**
|
|
|
|
* Internal Function, used to initialize the Dispatcher.
|
|
|
|
* It subscribes to the "Messages" of the communicator.
|
|
|
|
*
|
|
|
|
* @protected
|
|
|
|
* @memberof nopeDispatcher
|
|
|
|
*/
|
|
|
|
protected init(): void {
|
2020-09-12 00:59:30 +00:00
|
|
|
const _this = this;
|
|
|
|
|
|
|
|
// Based on the Mode of the Subscription =>
|
|
|
|
// either create indivdual topics for the methods
|
|
|
|
// or use the generice function.
|
|
|
|
switch (this.options.subscriptionMode) {
|
|
|
|
case 'individual':
|
|
|
|
// Iterate over the Defined Functions.
|
|
|
|
for (const [id, cb] of this._definedFunctions.entries()) {
|
|
|
|
// Subscribe the Function
|
|
|
|
this._subscribeToFunction(id, cb);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'generic':
|
|
|
|
// Add a generic Subscription for callbacks:
|
|
|
|
this._communicator.on('request', (data: requestTask) => {
|
|
|
|
if (data.type === 'request') {
|
|
|
|
_this._handleExternalRequest(data);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Subscribe to Responses
|
|
|
|
this._communicator.on('response', (data: responseOfTask) => {
|
|
|
|
if (data.type === 'response') {
|
|
|
|
_this._handleExternalResponse(data);
|
2020-08-21 16:38:21 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-09-12 00:59:30 +00:00
|
|
|
protected _getRequestName(id: string) {
|
|
|
|
return id.startsWith('request/') ? id : 'request/' + id;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected _subscribeToFunction(id: string, cb: (...args) => Promise<any>) {
|
|
|
|
if (
|
|
|
|
this.options.subscriptionMode === 'individual' &&
|
|
|
|
!this._communicatorCallbacks.has(this._getRequestName(id))
|
|
|
|
) {
|
|
|
|
|
|
|
|
const _this = this;
|
|
|
|
|
|
|
|
// Define a Function.
|
|
|
|
const func = (data: requestTask) => {
|
|
|
|
if (data.type === 'request') {
|
|
|
|
_this._handleExternalRequest(data, cb);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Add the Callback.
|
|
|
|
this._communicatorCallbacks.set(this._getRequestName(id), func);
|
|
|
|
|
|
|
|
// Register Function
|
|
|
|
this._communicator.on(this._getRequestName(id), func);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-21 16:38:21 +00:00
|
|
|
/**
|
2020-09-11 07:59:23 +00:00
|
|
|
* Function to register a Function in the Dispatcher
|
|
|
|
*
|
|
|
|
* @param {(...args) => Promise<any>} func The function which should be called if a request is mapped to the Function.
|
|
|
|
* @param {{
|
|
|
|
* // Flag to enable unregistering the function after calling.
|
|
|
|
* deleteAfterCalling?: boolean,
|
|
|
|
* // Instead of generating a uuid an id could be provided
|
|
|
|
* id?: string;
|
|
|
|
* }} [options={}] Options to enhance the registered ID and enabling unregistering the Element after calling it.
|
|
|
|
* @return {*} {(...args) => Promise<any>} The registered Function
|
|
|
|
* @memberof nopeDispatcher
|
2020-08-21 16:38:21 +00:00
|
|
|
*/
|
|
|
|
public registerFunction(func: (...args) => Promise<any>, options: {
|
2020-09-11 07:59:23 +00:00
|
|
|
/** Flag to enable unregistering the function after calling. */
|
2020-08-21 16:38:21 +00:00
|
|
|
deleteAfterCalling?: boolean,
|
2020-09-11 07:59:23 +00:00
|
|
|
/** Instead of generating a uuid an id could be provided */
|
2020-08-21 16:38:21 +00:00
|
|
|
id?: string;
|
2020-09-12 00:59:30 +00:00
|
|
|
/** Flag to enable / disable sending to registery */
|
|
|
|
preventSendingToRegistery?: boolean;
|
2020-09-11 07:59:23 +00:00
|
|
|
} = {}): (...args) => Promise<any> {
|
2020-08-21 16:38:21 +00:00
|
|
|
|
|
|
|
const _this = this;
|
2020-09-12 00:59:30 +00:00
|
|
|
let _id = options.id || generateId();
|
|
|
|
|
|
|
|
// if (this.options.subscriptionMode === 'generic') {
|
|
|
|
// _id = this._getRequestName(_id);
|
|
|
|
// }
|
|
|
|
|
|
|
|
_id = this._getRequestName(_id);
|
2020-08-21 16:38:21 +00:00
|
|
|
|
|
|
|
let _func = func;
|
|
|
|
|
|
|
|
if (options.deleteAfterCalling) {
|
|
|
|
_func = async (...args) => {
|
|
|
|
// Unregister the Method
|
|
|
|
_this.unregistFunction(_id);
|
|
|
|
// Return the Result of the Original Function.
|
|
|
|
return await func(...args);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Define a ID for the Function
|
|
|
|
_func['id'] = _id;
|
|
|
|
|
|
|
|
// Define the callback.
|
2020-09-12 00:59:30 +00:00
|
|
|
_func['unregister'] = () => _this.unregistFunction(_id);
|
2020-08-21 16:38:21 +00:00
|
|
|
|
|
|
|
// Reister the Function
|
|
|
|
this._definedFunctions.set(_func['id'], _func);
|
|
|
|
|
2020-09-12 00:59:30 +00:00
|
|
|
// Register the Callback:
|
|
|
|
this._subscribeToFunction(_id, _func);
|
|
|
|
|
|
|
|
if (!options.preventSendingToRegistery)
|
|
|
|
// Publish the Available Services.
|
|
|
|
this._sendAvailableServices();
|
|
|
|
|
2020-08-21 16:38:21 +00:00
|
|
|
// Return the Function.
|
|
|
|
return _func;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function to unregister a Function from the Dispatcher
|
2020-09-11 07:59:23 +00:00
|
|
|
* @param {(((...args) => void) | string | number)} func The Function to unregister
|
|
|
|
* @return {*} {boolean} Flag, whether the element was removed (only if found) or not.
|
|
|
|
* @memberof nopeDispatcher
|
2020-08-21 16:38:21 +00:00
|
|
|
*/
|
2020-09-11 07:59:23 +00:00
|
|
|
public unregistFunction(func: ((...args) => void) | string | number): boolean {
|
2020-09-12 00:59:30 +00:00
|
|
|
const _id = typeof func === 'string' ? func : func['id'] as string || '0';
|
|
|
|
|
|
|
|
// Try to unregister the Callback from the communcator:
|
|
|
|
if (this._communicatorCallbacks.has(_id)) {
|
|
|
|
// Unregister the Function
|
|
|
|
this._communicator.off(_id, this._communicatorCallbacks.get(_id));
|
|
|
|
// Remove the Callback
|
|
|
|
this._communicatorCallbacks.delete(_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Publish the Available Services.
|
|
|
|
this._sendAvailableServices();
|
|
|
|
|
2020-08-21 16:38:21 +00:00
|
|
|
return this._definedFunctions.delete(_id);
|
|
|
|
}
|
|
|
|
|
2020-09-12 00:59:30 +00:00
|
|
|
/**
|
|
|
|
* Function used to update the Available Services.
|
|
|
|
*
|
|
|
|
* @protected
|
|
|
|
* @memberof nopeDispatcher
|
|
|
|
*/
|
|
|
|
protected _sendAvailableServices() {
|
|
|
|
|
|
|
|
// Define the Message
|
|
|
|
const message: availableServices = {
|
|
|
|
dispatcher: this.id,
|
|
|
|
services: Array.from(this._definedFunctions.keys())
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send the Message.
|
|
|
|
this._communicator.send('availableServices', message);
|
|
|
|
}
|
|
|
|
|
2020-09-11 07:59:23 +00:00
|
|
|
/**
|
|
|
|
* Function which is used to perform a call on the remote.
|
|
|
|
*
|
|
|
|
* @template T
|
|
|
|
* @param {string} functionName The Name / ID of the Function
|
|
|
|
* @param {any[]} params The provided Parameters.
|
|
|
|
* @param {({
|
|
|
|
* deletableCallbacks: Array<number>;
|
|
|
|
* })} [options={
|
|
|
|
* deletableCallbacks: []
|
|
|
|
* }] You could provide the index of removeable callbacks.
|
|
|
|
* @return {*} {Promise<T>} The result of the Operation
|
|
|
|
* @memberof nopeDispatcher
|
|
|
|
*/
|
2020-08-21 16:38:21 +00:00
|
|
|
public performCall<T>(functionName: string, params: any[], options: {
|
2020-09-11 07:59:23 +00:00
|
|
|
deletableCallbacks: Array<number>;
|
2020-09-12 00:59:30 +00:00
|
|
|
noCallbackItegrated?: boolean;
|
|
|
|
noErrorTest?: boolean;
|
2020-08-21 16:38:21 +00:00
|
|
|
} = {
|
2020-09-12 00:59:30 +00:00
|
|
|
deletableCallbacks: [],
|
|
|
|
noCallbackItegrated: false,
|
|
|
|
noErrorTest: true
|
2020-09-11 07:59:23 +00:00
|
|
|
}): Promise<T> {
|
2020-08-21 16:38:21 +00:00
|
|
|
// Get a Call Id
|
2020-09-10 16:21:01 +00:00
|
|
|
const _taskId = generateId();
|
2020-08-21 16:38:21 +00:00
|
|
|
const _registeredIdx: Array<number | string> = [];
|
|
|
|
const _this = this;
|
|
|
|
|
|
|
|
// Define a Callback-Function, which will expect the Task.
|
|
|
|
return new Promise<T>((resolve, reject) => {
|
|
|
|
|
|
|
|
try {
|
|
|
|
// Register the Handlers,
|
|
|
|
_this._runningTasks.set(_taskId, {
|
|
|
|
resolve,
|
|
|
|
reject
|
|
|
|
});
|
|
|
|
|
2020-09-12 00:59:30 +00:00
|
|
|
// Test if there is no Callback integrated => Speedup the Function.
|
|
|
|
if (options.noCallbackItegrated) {
|
|
|
|
// Perform the call. Therefore create the data package.
|
|
|
|
const packet: requestTask = {
|
|
|
|
functionId: this._getRequestName(functionName),
|
|
|
|
params,
|
|
|
|
callbacks: [],
|
|
|
|
taskId: _taskId,
|
|
|
|
type: 'request'
|
|
|
|
}
|
2020-08-21 16:38:21 +00:00
|
|
|
|
2020-09-12 00:59:30 +00:00
|
|
|
// Send the Message, to the general Request Path:
|
|
|
|
_this._communicator.send('request', packet);
|
2020-08-21 16:38:21 +00:00
|
|
|
|
2020-09-12 00:59:30 +00:00
|
|
|
// Send the Message to the specific element:
|
|
|
|
if (_this.options.subscriptionMode === 'individual') {
|
|
|
|
_this._communicator.send(packet.functionId, packet);
|
|
|
|
}
|
2020-08-21 16:38:21 +00:00
|
|
|
|
2020-09-12 00:59:30 +00:00
|
|
|
// leave the Method.
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
|
|
|
|
const _parameters: {
|
|
|
|
idx: number,
|
|
|
|
data: any,
|
|
|
|
}[] = [];
|
|
|
|
|
|
|
|
const _callbacks: ({
|
|
|
|
functionId: string,
|
|
|
|
idx: number,
|
|
|
|
deleteAfterCalling: boolean,
|
|
|
|
} & callOptions)[] = [];
|
|
|
|
|
|
|
|
// Detail the Parameters.
|
|
|
|
for (const [idx, data] of params.entries()) {
|
|
|
|
if (typeof data !== "function") {
|
|
|
|
_parameters.push({
|
|
|
|
idx,
|
|
|
|
data
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
|
|
|
|
const deleteAfterCalling = options.deletableCallbacks.includes(idx);
|
|
|
|
const _func = _this.registerFunction(data, {
|
|
|
|
deleteAfterCalling,
|
|
|
|
preventSendingToRegistery: true
|
|
|
|
});
|
|
|
|
|
|
|
|
_registeredIdx.push(_func['id']);
|
|
|
|
|
|
|
|
// Register the Callback
|
|
|
|
_callbacks.push({
|
|
|
|
functionId: _func['id'],
|
|
|
|
idx,
|
|
|
|
deleteAfterCalling,
|
|
|
|
noErrorTest: true,
|
|
|
|
deletableCallbacks: []
|
|
|
|
});
|
|
|
|
}
|
2020-08-21 16:38:21 +00:00
|
|
|
}
|
|
|
|
|
2020-09-12 00:59:30 +00:00
|
|
|
// Perform the call. Therefore create the data package.
|
|
|
|
const packet: requestTask = {
|
|
|
|
functionId: _this._getRequestName(functionName),
|
|
|
|
params: _parameters,
|
|
|
|
callbacks: _callbacks,
|
|
|
|
taskId: _taskId,
|
|
|
|
type: 'request'
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send the Message to the specific element:
|
|
|
|
if (_this.options.subscriptionMode === 'individual') {
|
|
|
|
if (!options.noErrorTest) {
|
|
|
|
// Send the Message, to the general Request Path:
|
|
|
|
_this._communicator.send('request', packet);
|
|
|
|
}
|
|
|
|
_this._communicator.send(packet.functionId, packet);
|
|
|
|
} else {
|
|
|
|
_this._communicator.send('request', packet);
|
|
|
|
}
|
2020-08-21 16:38:21 +00:00
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
// Delete all Callbacks.
|
|
|
|
_registeredIdx.map(id => _this.unregistFunction(id));
|
|
|
|
|
|
|
|
// Remove the task:
|
2020-09-12 00:59:30 +00:00
|
|
|
if (_this._runningTasks.has(_taskId))
|
|
|
|
_this._runningTasks.delete(_taskId);
|
2020-08-21 16:38:21 +00:00
|
|
|
|
|
|
|
// Throw an error.
|
|
|
|
reject(e);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-09-11 07:59:23 +00:00
|
|
|
/**
|
|
|
|
* Function to clear all pending tasks
|
|
|
|
*
|
|
|
|
* @memberof nopeDispatcher
|
|
|
|
*/
|
|
|
|
public clearTasks(): void {
|
2020-08-21 16:38:21 +00:00
|
|
|
if (this._runningTasks)
|
|
|
|
this._runningTasks.clear();
|
|
|
|
else
|
|
|
|
this._runningTasks = new Map<number, {
|
|
|
|
resolve: (value: any) => void;
|
|
|
|
reject: (error: any) => void;
|
|
|
|
}>();
|
|
|
|
}
|
|
|
|
|
2020-09-11 07:59:23 +00:00
|
|
|
/**
|
|
|
|
* Function to unregister all Functions of the Dispatcher.
|
|
|
|
*
|
|
|
|
* @memberof nopeDispatcher
|
|
|
|
*/
|
|
|
|
public unregisterAll(): void {
|
2020-09-12 00:59:30 +00:00
|
|
|
if (this._definedFunctions) {
|
|
|
|
for (const id of this._definedFunctions.keys()) {
|
|
|
|
this.unregistFunction(id)
|
|
|
|
}
|
2020-08-21 16:38:21 +00:00
|
|
|
this._definedFunctions.clear();
|
2020-09-12 00:59:30 +00:00
|
|
|
} else {
|
2020-08-21 16:38:21 +00:00
|
|
|
this._definedFunctions = new Map<string, (...args) => Promise<any>>();
|
2020-09-12 00:59:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Reset the Callbacks.
|
|
|
|
this._communicatorCallbacks = new Map<string, (data) => any>();
|
2020-08-21 16:38:21 +00:00
|
|
|
}
|
|
|
|
|
2020-09-11 07:59:23 +00:00
|
|
|
/**
|
|
|
|
* Function to reset the Dispatcher.
|
|
|
|
*
|
|
|
|
* @memberof nopeDispatcher
|
|
|
|
*/
|
|
|
|
public reset(): void {
|
2020-08-21 16:38:21 +00:00
|
|
|
this.clearTasks();
|
|
|
|
this.unregisterAll();
|
|
|
|
}
|
|
|
|
}
|