在我的Angular 2应用程序中,我使用promises实现了一个简单的服务缓存,它工作正常。但是,我对我的实施还不满意:
export class Cache<T extends Cacheable<T, I>, I> {
items: T[];
init(items: T[]): void {
this.items = items;
}
isInitialised(): boolean {
return this.items != null;
}
all(): Promise<T[]> {
return Promise.resolve(this.items);
}
get(id: I): Promise<T> {
return Promise.resolve(this.items.find(item => item.id == id));
}
put(item: T): void {
this.items.push(item);
}
update(item: T): void {
this.get(item.id)
.then(cached => cached.copy(item));
}
remove(id: I): void {
let index = this.items.findIndex(item => item.id == id);
if (index > -1) {
this.items.splice(index, 1);
}
}
}
无论调用哪种方法,我都希望缓存初始化,无论是.all
,.get
等等。但是,关键是我想要第一次调用{{ 1}}强制缓存初始化。任何后续调用都应该等到缓存初始化之后再操作'this.items'。
为此,我想到了使用代理方法this.items
,它会返回一个promise,并用该方法替换对.itemsProxy()
的任何调用,并因此调整代码。这需要具有.items
,NOT_INITIALSED
或INITIALSING
的缓存状态。
代理方法如下所示:
INITIALSED
注意如何通过export class Cache<T extends Cacheable<T, I>, I> {
constructor(private service: AbstractService) {}
initPromise: Promise<T[]>;
state: NOT_INITIALISED;
itemsProxy(): Promise<T> {
if (this.state == INITIALISED)
return Promise.resolve(this.items);
if (this.state == NOT_INITIALISED) {
this.initPromise = this.service.all().then(items => {
// Avoid override when multiple subscribers
if (this.state != INITIALISED) {
this.items = items;
this.state = INITIALISED;
}
return this.items;
});
this.state = INITIALISING;
}
return this.initPromise;
}
...
}
完成初始化,如下所示:
this.service.all()
请注意,all(): Promise<T[]> {
if (this.cache.isInitialised()) {
return this.cache.all();
}
return this.http
.get(...)
.toPromise()
.then(response => {
this.cache.init(
response.json().data.map(item => new T(item))
);
return this.cache.all();
}); // No catch for demo
}
无效,但我为演示目的简化了代码。
上述解决方案似乎没有像我期望的那样工作,异步调用很难调试。
我想让new T(...)
成为this.items
,每次调用都会订阅它。但是,我对可观察量的理解是非常有限的:我不知道订阅者是否可以修改它所订阅的可观察数据(即可观察的可变性如T []?)。另外,在我看来,observable“产生”结果,所以在初始化缓存之后,任何新订阅者都能够访问由observable生成的数据吗?
您将如何实现这种“同步”机制?