aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2020-07-27 17:43:46 +0800
committercrupest <crupest@outlook.com>2020-07-27 17:43:46 +0800
commitc10218d8d5ec01ae29c0b2880a8d6af371a562e5 (patch)
treec86309b2c68ba3e9ffc1973e406f02b7fd4609cf
parente26b101fdec6cacb54d09e66c0ef06cfad5e490c (diff)
downloadtimeline-c10218d8d5ec01ae29c0b2880a8d6af371a562e5.tar.gz
timeline-c10218d8d5ec01ae29c0b2880a8d6af371a562e5.tar.bz2
timeline-c10218d8d5ec01ae29c0b2880a8d6af371a562e5.zip
Add post list subscription hub.
-rw-r--r--Timeline/ClientApp/src/app/data/SubscriptionHub.ts32
-rw-r--r--Timeline/ClientApp/src/app/data/timeline.ts22
2 files changed, 41 insertions, 13 deletions
diff --git a/Timeline/ClientApp/src/app/data/SubscriptionHub.ts b/Timeline/ClientApp/src/app/data/SubscriptionHub.ts
index 2bc6de56..92a54bc7 100644
--- a/Timeline/ClientApp/src/app/data/SubscriptionHub.ts
+++ b/Timeline/ClientApp/src/app/data/SubscriptionHub.ts
@@ -3,6 +3,8 @@
// 2. We need a way to finalize the last object. For example, if it has an object url, we need to revoke it.
// 3. Make api easier to use and write less boilerplate codes.
//
+// Currently updator will wait for last update or creation to finish. So the old data passed to it will always be right. We may add feature for just cancel last one but not wait for it.
+//
// There might be some bugs, especially memory leaks and in asynchronization codes.
import * as rxjs from 'rxjs';
@@ -23,7 +25,7 @@ class SubscriptionToken {
}
class SubscriptionLine<TData> {
- private _lastDataPromise: Promise<void>;
+ private _lastDataPromise: Promise<TData>;
private _dataSubject = new rxjs.BehaviorSubject<TData | undefined>(undefined);
private _data$: rxjs.Observable<TData> = this._dataSubject.pipe(
filter((d) => d !== undefined)
@@ -32,11 +34,12 @@ class SubscriptionLine<TData> {
constructor(
_creator: () => Promise<TData>,
- private _destroyer: (data: TData) => void,
+ private _destroyer: ((data: TData) => void) | undefined,
private _onZeroRef: (self: SubscriptionLine<TData>) => void
) {
this._lastDataPromise = _creator().then((data) => {
this._dataSubject.next(data);
+ return data;
});
}
@@ -50,25 +53,25 @@ class SubscriptionLine<TData> {
token._subscription.unsubscribe();
this._refCount -= 1;
if (this._refCount === 0) {
- void this._lastDataPromise.then(() => {
- const last = this._dataSubject.value;
- if (last !== undefined) {
- this._destroyer(last);
+ void this._lastDataPromise.then((data) => {
+ if (this._destroyer != null && data !== undefined) {
+ this._destroyer(data);
}
});
this._onZeroRef(this);
}
}
- next(updator: () => Promise<TData>): void {
+ next(updator: (old: TData) => Promise<TData>): void {
this._lastDataPromise = this._lastDataPromise
- .then(() => updator())
+ .then((old) => updator(old))
.then((data) => {
const last = this._dataSubject.value;
- if (last !== undefined) {
+ if (this._destroyer != null && last !== undefined) {
this._destroyer(last);
}
this._dataSubject.next(data);
+ return data;
});
}
}
@@ -82,7 +85,7 @@ export class SubscriptionHub<TKey, TData>
constructor(
public keyToString: (key: TKey) => string,
public creator: (key: TKey) => Promise<TData>,
- public destroyer: (key: TKey, data: TData) => void
+ public destroyer?: (key: TKey, data: TData) => void
) {}
private subscriptionLineMap = new Map<string, SubscriptionLine<TData>>();
@@ -92,11 +95,14 @@ export class SubscriptionHub<TKey, TData>
const line = (() => {
const savedLine = this.subscriptionLineMap.get(keyString);
if (savedLine == null) {
+ const { destroyer } = this;
const newLine = new SubscriptionLine<TData>(
() => this.creator(key),
- (data) => {
- this.destroyer(key, data);
- },
+ destroyer != null
+ ? (data) => {
+ destroyer(key, data);
+ }
+ : undefined,
() => {
this.subscriptionLineMap.delete(keyString);
}
diff --git a/Timeline/ClientApp/src/app/data/timeline.ts b/Timeline/ClientApp/src/app/data/timeline.ts
index dde204be..f2c3fdda 100644
--- a/Timeline/ClientApp/src/app/data/timeline.ts
+++ b/Timeline/ClientApp/src/app/data/timeline.ts
@@ -126,6 +126,28 @@ export class TimelineService {
);
}
+ private _postListSubscriptionHub = new SubscriptionHub<
+ string,
+ TimelinePostInfo[]
+ >(
+ (key) => key,
+ async (key) => {
+ return (
+ await getHttpTimelineClient().listPost(
+ key,
+ userService.currentUser?.token
+ )
+ ).map((post) => ({
+ ...post,
+ timelineName: key,
+ }));
+ }
+ );
+
+ get postListSubscriptionHub(): ISubscriptionHub<string, TimelinePostInfo[]> {
+ return this._postListSubscriptionHub;
+ }
+
private _postDataSubscriptionHub = new SubscriptionHub<PostKey, BlobWithUrl>(
(key) => `${key.timelineName}/${key.postId}`,
async (key) => {