introduced remotedata selector

This commit is contained in:
Art Lowel
2017-03-16 14:44:54 +01:00
parent a4579e5435
commit a62c8d62c0
2 changed files with 104 additions and 19 deletions

View File

@@ -6,6 +6,7 @@ import { CacheableObject } from "../cache/object-cache.reducer";
import { ParamHash } from "../shared/param-hash"; import { ParamHash } from "../shared/param-hash";
import { isNotEmpty } from "../../shared/empty.util"; import { isNotEmpty } from "../../shared/empty.util";
import { GenericConstructor } from "../shared/generic-constructor"; import { GenericConstructor } from "../shared/generic-constructor";
import { RemoteData } from "./remote-data";
export abstract class DataService<T extends CacheableObject> { export abstract class DataService<T extends CacheableObject> {
abstract serviceName: OpaqueToken; abstract serviceName: OpaqueToken;
@@ -16,20 +17,28 @@ export abstract class DataService<T extends CacheableObject> {
} }
findAll(scopeID?: string): Observable<Array<T>> { findAll(scopeID?: string): RemoteData<Array<T>> {
const key = new ParamHash(this.serviceName, 'findAll', scopeID).toString(); const key = new ParamHash(this.serviceName, 'findAll', scopeID).toString();
return this.requestCache.findAll(key, this.serviceName, scopeID) const requestCacheObs = this.requestCache.findAll(key, this.serviceName, scopeID);
//get an observable of the IDs from the RequestCache return new RemoteData(
requestCacheObs.map(entry => entry.isLoading).distinctUntilChanged(),
requestCacheObs.map(entry => entry.errorMessage).distinctUntilChanged(),
requestCacheObs
.map(entry => entry.resourceUUIDs) .map(entry => entry.resourceUUIDs)
.flatMap((resourceUUIDs: Array<string>) => { .flatMap((resourceUUIDs: Array<string>) => {
// use those IDs to fetch the actual objects from the ObjectCache // use those IDs to fetch the actual objects from the ObjectCache
return this.objectCache.getList<T>(resourceUUIDs, this.modelType); return this.objectCache.getList<T>(resourceUUIDs, this.modelType);
}); }).distinctUntilChanged()
);
} }
findById(id: string): Observable<T> { findById(id: string): RemoteData<T> {
const key = new ParamHash(this.serviceName, 'findById', id).toString(); const key = new ParamHash(this.serviceName, 'findById', id).toString();
return this.requestCache.findById(key, this.serviceName, id) const requestCacheObs = this.requestCache.findById(key, this.serviceName, id);
return new RemoteData(
requestCacheObs.map(entry => entry.isLoading).distinctUntilChanged(),
requestCacheObs.map(entry => entry.errorMessage).distinctUntilChanged(),
requestCacheObs
.map(entry => entry.resourceUUIDs) .map(entry => entry.resourceUUIDs)
.flatMap((resourceUUIDs: Array<string>) => { .flatMap((resourceUUIDs: Array<string>) => {
if (isNotEmpty(resourceUUIDs)) { if (isNotEmpty(resourceUUIDs)) {
@@ -38,7 +47,8 @@ export abstract class DataService<T extends CacheableObject> {
else { else {
return Observable.of(undefined); return Observable.of(undefined);
} }
}); }).distinctUntilChanged()
);
} }
} }

View File

@@ -0,0 +1,75 @@
import { Observable } from "rxjs";
import { hasValue } from "../../shared/empty.util";
export enum RemoteDataState {
//TODO RequestPending will never happen: implement it in the store & DataEffects.
RequestPending,
ResponsePending,
Failed,
Success
}
/**
* A class to represent the state of
*/
export class RemoteData<T> {
constructor(
private storeLoading: Observable<boolean>,
public errorMessage: Observable<string>,
public payload: Observable<T>
) {
}
get state(): Observable<RemoteDataState> {
return Observable.combineLatest(
this.storeLoading,
this.errorMessage.map(msg => hasValue(msg)),
(storeLoading, hasMsg) => {
if (storeLoading) {
return RemoteDataState.ResponsePending
}
else if (hasMsg) {
return RemoteDataState.Failed
}
else {
return RemoteDataState.Success
}
}
).distinctUntilChanged();
}
get isRequestPending(): Observable<boolean> {
return this.state
.map(state => state == RemoteDataState.RequestPending)
.distinctUntilChanged();
}
get isResponsePending(): Observable<boolean> {
return this.state
.map(state => state == RemoteDataState.ResponsePending)
.distinctUntilChanged();
}
get isLoading(): Observable<boolean> {
return this.state
.map(state => {
return state == RemoteDataState.RequestPending
|| state === RemoteDataState.ResponsePending
})
.distinctUntilChanged();
}
get hasFailed(): Observable<boolean> {
return this.state
.map(state => state == RemoteDataState.Failed)
.distinctUntilChanged();
}
get hasSucceeded(): Observable<boolean> {
return this.state
.map(state => state == RemoteDataState.Success)
.distinctUntilChanged();
}
}