2020-11-24 14:14:56 +00:00
|
|
|
/**
|
|
|
|
* @author Martin Karkowski
|
|
|
|
* @email m.karkowski@zema.de
|
|
|
|
* @create date 2020-11-23 08:06:30
|
2021-11-14 22:16:07 +00:00
|
|
|
* @modify date 2021-11-14 09:03:39
|
2020-11-24 14:14:56 +00:00
|
|
|
* @desc [description]
|
|
|
|
*/
|
|
|
|
|
2021-11-14 22:16:07 +00:00
|
|
|
import { BehaviorSubject } from "rxjs";
|
|
|
|
import { NopeEventEmitter } from "../eventEmitter/nopeEventEmitter";
|
|
|
|
import { TSubjectOptions } from "../helpers/getSubject";
|
2020-11-24 14:14:56 +00:00
|
|
|
import { generateId } from "../helpers/idMethods";
|
2021-10-18 06:02:29 +00:00
|
|
|
import { getNopeLogger } from "../logger/getLogger";
|
2020-12-04 18:10:33 +00:00
|
|
|
import {
|
2021-12-04 07:25:26 +00:00
|
|
|
IEventAdditionalData,
|
|
|
|
IEventCallback,
|
|
|
|
INopeObservable,
|
2020-12-04 18:10:33 +00:00
|
|
|
INopeObserver,
|
|
|
|
INopePartialObserver,
|
2021-12-04 07:25:26 +00:00
|
|
|
INopeSubscriptionOptions,
|
|
|
|
IObservableType,
|
2021-11-14 22:16:07 +00:00
|
|
|
} from "../types/nope/index";
|
2020-08-21 14:49:48 +00:00
|
|
|
|
2021-10-18 06:02:29 +00:00
|
|
|
const logger = getNopeLogger("obervable");
|
|
|
|
|
2020-08-21 14:49:48 +00:00
|
|
|
/**
|
|
|
|
* RsJX based Observable.
|
2020-12-04 18:10:33 +00:00
|
|
|
*
|
2020-08-21 14:49:48 +00:00
|
|
|
* Contains additional Functionalities like:
|
|
|
|
* - property with the current value
|
|
|
|
* - function to publish values. (wrapper for next)
|
|
|
|
* - enables performing a subscription with synced call or a immediate call.
|
|
|
|
*/
|
2022-01-07 17:12:08 +00:00
|
|
|
export class NopeObservable<
|
|
|
|
T,
|
|
|
|
S = T,
|
|
|
|
G = T,
|
|
|
|
AD extends IEventAdditionalData = IEventAdditionalData
|
|
|
|
>
|
|
|
|
extends NopeEventEmitter<T, S, G, AD>
|
|
|
|
implements INopeObservable<T, S, G, AD>
|
2021-08-30 04:40:51 +00:00
|
|
|
{
|
2022-01-07 17:12:08 +00:00
|
|
|
protected _emitter: BehaviorSubject<IObservableType<G, AD>>;
|
2021-11-14 22:16:07 +00:00
|
|
|
|
2022-01-07 17:12:08 +00:00
|
|
|
public get observable(): BehaviorSubject<IObservableType<G, AD>> {
|
2021-11-14 22:16:07 +00:00
|
|
|
return this._emitter;
|
|
|
|
}
|
2020-08-25 22:11:26 +00:00
|
|
|
|
|
|
|
public readonly id: string = generateId();
|
2020-08-21 14:49:48 +00:00
|
|
|
|
2020-08-25 22:11:26 +00:00
|
|
|
public _value: T;
|
|
|
|
|
2021-10-19 19:27:30 +00:00
|
|
|
public options: any = {
|
2021-12-04 07:25:26 +00:00
|
|
|
generateTimeStamp: true,
|
2021-10-19 19:27:30 +00:00
|
|
|
};
|
2020-08-21 14:49:48 +00:00
|
|
|
|
2022-01-07 17:12:08 +00:00
|
|
|
public setContent(value: S | null, options: Partial<AD> = {}): boolean {
|
2021-11-14 22:16:07 +00:00
|
|
|
return this._emit(value, options);
|
|
|
|
}
|
|
|
|
|
2020-08-30 10:00:31 +00:00
|
|
|
/**
|
2021-10-19 19:27:30 +00:00
|
|
|
* Function to set the content of the Observable
|
2020-12-04 18:10:33 +00:00
|
|
|
* @param value
|
|
|
|
* @param sender
|
|
|
|
* @param timeStamp
|
|
|
|
* @param data
|
2020-08-30 10:00:31 +00:00
|
|
|
*/
|
2022-01-07 17:12:08 +00:00
|
|
|
protected _emit(value: S | null, options: Partial<AD> = {}): boolean {
|
2020-08-30 10:00:31 +00:00
|
|
|
// Change the Value.
|
|
|
|
if (this.setter !== null) {
|
2022-01-07 17:12:08 +00:00
|
|
|
const adapted = this.setter(value as S, options);
|
2020-08-25 22:11:26 +00:00
|
|
|
|
2020-08-30 10:00:31 +00:00
|
|
|
if (!adapted.valid) {
|
2020-11-24 14:14:56 +00:00
|
|
|
return false;
|
2020-08-30 10:00:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
this._value = adapted.data;
|
|
|
|
} else {
|
|
|
|
// Adapt the Value if required.
|
2021-08-30 04:40:51 +00:00
|
|
|
this._value = value as any as T;
|
2020-08-30 10:00:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const valueToPublish = this.getContent();
|
|
|
|
|
|
|
|
/** Publish the Data */
|
2021-12-04 07:25:26 +00:00
|
|
|
if (
|
|
|
|
!this.disablePublishing &&
|
|
|
|
(options.forced || this._emitter.value?.value !== valueToPublish)
|
|
|
|
) {
|
2021-10-19 19:27:30 +00:00
|
|
|
return this._publish(valueToPublish, options);
|
2020-08-30 10:00:31 +00:00
|
|
|
}
|
2020-11-16 12:06:45 +00:00
|
|
|
|
|
|
|
return false;
|
2020-08-30 10:00:31 +00:00
|
|
|
}
|
2020-08-25 22:11:26 +00:00
|
|
|
|
2020-08-30 10:00:31 +00:00
|
|
|
/**
|
|
|
|
* Internal Function to Publish content
|
2021-10-19 19:27:30 +00:00
|
|
|
*
|
|
|
|
* @author M.Karkowski
|
|
|
|
* @protected
|
|
|
|
* @param {G} value The value to use.
|
2022-01-07 17:12:08 +00:00
|
|
|
* @param {Partial<AD>} [options={}]
|
|
|
|
* @return {boolean}
|
2021-10-19 19:27:30 +00:00
|
|
|
* @memberof NopeObservable
|
2020-08-30 10:00:31 +00:00
|
|
|
*/
|
2022-01-07 17:12:08 +00:00
|
|
|
protected _publish(value: G, options: Partial<AD> = {}): boolean {
|
2020-08-30 10:00:31 +00:00
|
|
|
// Only Proceed if Publishing is required.
|
2021-10-19 19:27:30 +00:00
|
|
|
if (options.forced || this.disablePublishing === false) {
|
|
|
|
options = this._updateSenderAndTimestamp(options);
|
2020-08-25 22:11:26 +00:00
|
|
|
|
2021-10-19 19:27:30 +00:00
|
|
|
// Define the value.
|
2021-11-14 22:16:07 +00:00
|
|
|
this._emitter.next({ value, ...options });
|
2020-11-16 12:06:45 +00:00
|
|
|
|
|
|
|
return this.hasSubscriptions;
|
2020-08-25 22:11:26 +00:00
|
|
|
}
|
2020-11-16 12:06:45 +00:00
|
|
|
|
|
|
|
return false;
|
2020-08-21 14:49:48 +00:00
|
|
|
}
|
2020-09-01 14:56:26 +00:00
|
|
|
|
2020-08-30 10:00:31 +00:00
|
|
|
/**
|
2021-10-19 19:27:30 +00:00
|
|
|
* Function to Force an Update
|
|
|
|
*
|
|
|
|
* @author M.Karkowski
|
2022-01-07 17:12:08 +00:00
|
|
|
* @param {Partial<AD>} options Options which might be relevant
|
|
|
|
* @return {boolean}
|
2021-10-19 19:27:30 +00:00
|
|
|
* @memberof NopeObservable
|
2020-08-30 10:00:31 +00:00
|
|
|
*/
|
2022-01-07 17:12:08 +00:00
|
|
|
public forcePublish(options: Partial<AD> = {}): boolean {
|
2021-10-19 19:27:30 +00:00
|
|
|
options.forced = true;
|
|
|
|
return this._publish(this.getContent(), options);
|
2020-08-30 10:00:31 +00:00
|
|
|
}
|
2020-08-21 14:49:48 +00:00
|
|
|
|
2020-08-30 10:00:31 +00:00
|
|
|
/**
|
|
|
|
* Function to extract the Content.
|
|
|
|
* If a Getter is provided, the Getter will be used
|
|
|
|
* to Transform the item.
|
|
|
|
*/
|
|
|
|
public getContent(): G | null {
|
2020-12-04 18:10:33 +00:00
|
|
|
if (this.getter !== null) return this.getter(this._value);
|
2021-08-30 04:40:51 +00:00
|
|
|
return this._value as any as G;
|
2020-08-25 22:11:26 +00:00
|
|
|
}
|
|
|
|
|
2021-10-18 06:02:29 +00:00
|
|
|
protected _lastDataUpdate: number;
|
|
|
|
|
2020-08-30 08:32:48 +00:00
|
|
|
/**
|
|
|
|
* A Function to subscribe to updates of the Observable.
|
|
|
|
* @param observer The Observer. Could be a Function or a Partial Observer.
|
|
|
|
* @param mode The Mode of the Subscription
|
|
|
|
* @param options Additional Options.
|
|
|
|
*/
|
2020-12-04 18:10:33 +00:00
|
|
|
public subscribe(
|
2021-11-14 22:16:07 +00:00
|
|
|
observer: INopePartialObserver<G> | IEventCallback<G>,
|
2020-09-28 16:38:35 +00:00
|
|
|
options: INopeSubscriptionOptions = {
|
2021-10-19 19:27:30 +00:00
|
|
|
type: "sync",
|
2021-09-04 11:45:52 +00:00
|
|
|
mode: ["direct", "sub", "super"],
|
2021-12-04 07:25:26 +00:00
|
|
|
skipCurrent: false,
|
2020-12-04 18:10:33 +00:00
|
|
|
}
|
|
|
|
): INopeObserver {
|
2021-11-14 22:16:07 +00:00
|
|
|
return this._subscribe(observer, options);
|
2020-09-08 14:58:50 +00:00
|
|
|
}
|
2020-12-30 18:55:45 +00:00
|
|
|
|
2021-11-14 22:16:07 +00:00
|
|
|
constructor(protected _options: TSubjectOptions = {}) {
|
|
|
|
super(Object.assign(_options, { showCurrent: true }));
|
2020-12-30 18:55:45 +00:00
|
|
|
}
|
2020-12-04 18:10:33 +00:00
|
|
|
}
|