Compare commits
5 Commits
d0a65f7f4f
...
last_value
Author | SHA1 | Date | |
---|---|---|---|
564166a781 | |||
edd37246fb | |||
d1fdb789c1 | |||
11a3b00c12 | |||
9eef107d56 |
8
package-lock.json
generated
8
package-lock.json
generated
@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "@hibas123/utils",
|
"name": "@hibas123/utils",
|
||||||
"version": "2.0.0",
|
"version": "2.1.1",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"typescript": {
|
"typescript": {
|
||||||
"version": "3.3.3333",
|
"version": "3.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.3.3333.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz",
|
||||||
"integrity": "sha512-JjSKsAfuHBE/fB2oZ8NxtRTk5iGcg6hkYXMnZ3Wc+b2RSqejEqTaem11mHASMnFilHrax3sLK0GDzcJrekZYLw==",
|
"integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@hibas123/utils",
|
"name": "@hibas123/utils",
|
||||||
"version": "2.0.2",
|
"version": "2.1.1",
|
||||||
"description": "Different Utilities, that are not worth own packages",
|
"description": "Different Utilities, that are not worth own packages",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"types": "lib/index.d.ts",
|
"types": "lib/index.d.ts",
|
||||||
@ -16,12 +16,13 @@
|
|||||||
"type": "git"
|
"type": "git"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^3.3.3333"
|
"typescript": "^3.5.3"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
"src/",
|
||||||
"lib/",
|
"lib/",
|
||||||
"tsconfig.json",
|
"tsconfig.json",
|
||||||
"readme.md"
|
"readme.md"
|
||||||
],
|
],
|
||||||
"private": false
|
"private": false
|
||||||
}
|
}
|
||||||
|
@ -19,41 +19,86 @@ export type ObservableInterface<T> = {
|
|||||||
subscribeCollect: (callback: ObserverCallbackCollect<T>) => void;
|
subscribeCollect: (callback: ObserverCallbackCollect<T>) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ClosedSymbol = Symbol("Observable Closed");
|
||||||
|
const LastValueSymbol = Symbol("Observable LastValue");
|
||||||
|
|
||||||
export default class Observable<T = any> {
|
export default class Observable<T = any> {
|
||||||
private subscriber: ObserverCallback<T>[] = [];
|
private subscriber: ObserverCallback<T>[] = [];
|
||||||
private subscriberCollect: ObserverCallbackCollect<T>[] = [];
|
private subscriberCollect: ObserverCallbackCollect<T>[] = [];
|
||||||
private events: T[] = [];
|
private events: T[] = [];
|
||||||
private timeout: number | undefined = undefined;
|
private timeout: number | undefined = undefined;
|
||||||
|
|
||||||
|
// Use symbol to make sure this property cannot be changed from the outside
|
||||||
|
private [ClosedSymbol] = false;
|
||||||
|
|
||||||
|
private [LastValueSymbol]: T | undefined = undefined;
|
||||||
|
|
||||||
|
get lastValue() {
|
||||||
|
return this[LastValueSymbol];
|
||||||
|
}
|
||||||
|
|
||||||
|
get closed() {
|
||||||
|
return this[ClosedSymbol];
|
||||||
|
}
|
||||||
|
|
||||||
constructor(private collect_intervall: number = 100) { }
|
constructor(private collect_intervall: number = 100) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe to changes
|
||||||
|
* @param callback Callback called once a value is available
|
||||||
|
*/
|
||||||
|
subscribe(callback: ObserverCallback<T>) {
|
||||||
|
if (this[ClosedSymbol])
|
||||||
|
throw new Error("Observable is closed!");
|
||||||
|
|
||||||
|
let oldcb = this.subscriber.find(e => e === callback);
|
||||||
|
if (!oldcb)
|
||||||
|
this.subscriber.push(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsubscribe specified callback. After that, it will be discarded.
|
||||||
|
* @param callback The callback originally subscribed
|
||||||
|
*/
|
||||||
|
unsubscribe(callback: ObserverCallback<T> | ObserverCallbackCollect<T>) {
|
||||||
|
if (this[ClosedSymbol])
|
||||||
|
return;
|
||||||
|
|
||||||
|
let idx = this.subscriber.findIndex(e => e === callback);
|
||||||
|
if (idx >= 0) {
|
||||||
|
this.subscriber.splice(idx, 1);
|
||||||
|
} else {
|
||||||
|
idx = this.subscriberCollect.findIndex(e => e === callback);
|
||||||
|
if (idx >= 0)
|
||||||
|
this.subscriberCollect.splice(idx, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe for a collection of changes
|
||||||
|
* @param callback Callback called once a or some values are available.
|
||||||
|
*/
|
||||||
|
subscribeCollect(callback: ObserverCallbackCollect<T>) {
|
||||||
|
if (this[ClosedSymbol])
|
||||||
|
throw new Error("Observable is closed!");
|
||||||
|
|
||||||
|
let oldcb = this.subscriberCollect.find(e => e === callback);
|
||||||
|
if (!oldcb)
|
||||||
|
this.subscriberCollect.push(callback)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates Public API with subscribe and unsubscribe
|
* Creates Public API with subscribe and unsubscribe
|
||||||
*
|
*
|
||||||
* @returns {object}
|
* @returns {object}
|
||||||
*/
|
*/
|
||||||
getPublicApi(): ObservableInterface<T> {
|
getPublicApi(): ObservableInterface<T> {
|
||||||
|
if (this[ClosedSymbol])
|
||||||
|
throw new Error("Observable is closed!");
|
||||||
return {
|
return {
|
||||||
subscribe: (callback: ObserverCallback<T>) => {
|
subscribe: (callback: ObserverCallback<T>) => this.subscribe(callback),
|
||||||
let oldcb = this.subscriber.find(e => e === callback);
|
unsubscribe: (callback: ObserverCallback<T> | ObserverCallbackCollect<T>) => this.unsubscribe(callback),
|
||||||
if (!oldcb)
|
subscribeCollect: (callback: ObserverCallbackCollect<T>) => this.subscribeCollect(callback)
|
||||||
this.subscriber.push(callback)
|
|
||||||
},
|
|
||||||
unsubscribe: (callback: ObserverCallback<T> | ObserverCallbackCollect<T>) => {
|
|
||||||
let idx = this.subscriber.findIndex(e => e === callback);
|
|
||||||
if (idx >= 0) {
|
|
||||||
this.subscriber.splice(idx, 1);
|
|
||||||
} else {
|
|
||||||
idx = this.subscriberCollect.findIndex(e => e === callback);
|
|
||||||
if (idx >= 0)
|
|
||||||
this.subscriberCollect.splice(idx, 1);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
subscribeCollect: (callback: ObserverCallbackCollect<T>) => {
|
|
||||||
let oldcb = this.subscriberCollect.find(e => e === callback);
|
|
||||||
if (!oldcb)
|
|
||||||
this.subscriberCollect.push(callback)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,6 +107,10 @@ export default class Observable<T = any> {
|
|||||||
* @param data data to be sent
|
* @param data data to be sent
|
||||||
*/
|
*/
|
||||||
send(data: T) {
|
send(data: T) {
|
||||||
|
if (this[ClosedSymbol])
|
||||||
|
throw new Error("Observable is closed!");
|
||||||
|
|
||||||
|
this[LastValueSymbol] = data;
|
||||||
this.subscriber.forEach(e => e(data));
|
this.subscriber.forEach(e => e(data));
|
||||||
this.events.push(data);
|
this.events.push(data);
|
||||||
if (!this.timeout) {
|
if (!this.timeout) {
|
||||||
@ -69,8 +118,22 @@ export default class Observable<T = any> {
|
|||||||
this.subscriberCollect.forEach(cb => {
|
this.subscriberCollect.forEach(cb => {
|
||||||
cb(this.events)
|
cb(this.events)
|
||||||
});
|
});
|
||||||
|
this.events = [];
|
||||||
this.timeout = undefined;
|
this.timeout = undefined;
|
||||||
}, this.collect_intervall);
|
}, this.collect_intervall);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes Observable. This will remove all subscribers and mark this observable as closed.
|
||||||
|
* You won't be able to reopen this observable. All maybe collected data will be discardet.
|
||||||
|
*/
|
||||||
|
close() {
|
||||||
|
this[ClosedSymbol] = true;
|
||||||
|
this.subscriber = [];
|
||||||
|
this.subscriberCollect = [];
|
||||||
|
this.events = [];
|
||||||
|
if (this.timeout)
|
||||||
|
clearTimeout(this.timeout)
|
||||||
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user