我在其他地方也看到过类似的问题,但没有答案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' });
}
}然后在组件中,我将上面的观察值直接分配给模型上的一个属性,并使用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在控制台中被设置为下一个值)。
不过,单击该按钮会提供另一个'next‘值,然后UI会正确更新。看到这一切,似乎在第一个值被传递给主题之后,就订阅了可观察对象,所以UI没有得到那个初始值。我尝试了许多不同的方法,但都没有效果。我试着用BehaviorSubject代替。我还尝试使用shareReplay和其他运算符。我还尝试在ngAfterViewInit方法中设置observable。还是不走运。如果数据在本地存储中,我不认为用户应该立即采取一些操作来查看它,但我似乎找不到正确的方法来使其工作。
我如何正确地设置此可观察对象,以便它将从本地存储中获取信息并将其放入视图中,而无需用户执行某些操作?
这是一个包含代码的StackBlitz。
发布于 2019-07-24 21:42:05
这是一个标准的订阅时间问题...信号发出后,异步管道正在订阅...使其成为行为主体或重放主体,而不是向新订阅者广播最后一个主题值。
private testSubject: ReplaySubject<{ name: string }> = new ReplaySubject(1);https://stackoverflow.com/questions/57184325
复制相似问题