【发布时间】:2019-07-24 13:38:52
【问题描述】:
我在其他地方看到过与此类似的问题,但没有答案 1。
我有一项服务正在查看本地存储以获取价值。如果它在那里,它会将其设置为Subject 上的下一个值,否则它将进行 http 调用。
我知道下面是一个人为的例子,但我试图想出一个 MVP。
test.service.ts
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/internal/Subject';
@Injectable({ providedIn: 'root' })
export class TestService {
private testSubject: Subject<{ name: string }> = new Subject();
testObservable$ = this.testSubject.asObservable();
constructor() {
var cat = localStorage.getItem('myCat');
console.log(cat);
this.testSubject.next({ name: cat });
}
update() {
localStorage.setItem('myCat', 'Tom');
this.testSubject.next({ name: 'not Tom' });
}
}
然后在组件中,我将上面的 observable 直接分配给模型上的一个属性,并使用 async 管道将其公开给模板。
app.component.ts
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { TestService } from './test.service';
import { map } from 'rxjs/internal/operators/map';
@Component({
selector: 'my-app',
template: `
<p>
Hello {{test$ | async}}!
</p>
<button (click)="onClick()">Click me!</button>`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent {
test$ = this.testService
.testObservable$
.pipe(
map(a => a.name)
);
constructor(private testService: TestService) {
}
onClick() {
this.testService.update();
}
}
当我的视图呈现时,它没有显示名称 Tom,即使在我第一次单击按钮(将值放入本地存储)并重新加载页面(您可以看到 Tom 被设置为控制台中的下一个值)。
单击按钮虽然会提供另一个“下一个”值,但 UI 会正确更新。看到这一切,似乎在将第一个值传递给主题之后订阅了 observable,因此 UI 没有获得该初始值。我尝试了许多不同的事情都无济于事。我尝试使用 BehaviorSubject 代替。还尝试使用shareReplay 和其他运算符。我还尝试在 ngAfterViewInit 方法中设置 observable。仍然没有运气。如果数据在本地存储中,我认为用户不应该立即执行某些操作来查看它,但我似乎找不到让它工作的正确方法。
如何正确设置此 observable,以便它从本地存储中获取信息并将其放入视图中,而无需用户采取任何操作?
这是带有代码的StackBlitz。
【问题讨论】:
-
在构造函数中使用
this.testSubject.next很好,但当时没有人在听。所以你可能想改用ReplaySubject或BehaviorSubject。
标签: angular rxjs observable