【问题标题】:Async Pipe Fails to Render Observable异步管道无法渲染 Observable
【发布时间】:2016-07-19 16:54:22
【问题描述】:

e(1):更新代码以解决原始问题中的拼写错误。
e(2):尝试在“createContent()”中将数据推送到我的 JSON 对象中的“JSON.stringify()”。没有运气。
e(3):按要求添加 plnkrhttp://plnkr.co/edit/j024MYCQbypAGaf762fT

我有一个模型...

class Content {
  constructor(public name: string) { }
}

我有一个服务...

class ContentService {
  private _contents$: Subject<Content[]>
    = new Subject<Content[]>();

  get contents$(): Observable<Content[]> {
    return this._contents$.asObservable();
  }

  private _data: { contents: Content[] } = { contents: [] };

...

  load(): void {
    createContent(new Content("Test Content..."));
  }

  createContent(item: Content): void {
    this._data.contents.push(item);
    this._contents$.next(this._data.contents);
  }
}

我有一个组件...

@Component({
...
template: `
<h1 *ngFor="let item of contents$ | async">{{ item.name }}</h1>
`
})
class ContentListComponent {
  contents$: Observable<Content[]>;

  constructor(private _contentService: ContentService) { }

  ngOnInit(): void {
    this.contents$ = this._contentService.contents$;
    this._contentService.load();
  }
}

简单地说,我不明白为什么我的组件中的 Observable 不能正常工作。

如果我改变这些,比如我在组件中有一个数组,订阅服务'contents$'来填充数组,那么这没什么大不了的。

当我记录所调用的服务和函数的输出时,一切都很好。我遇到的唯一症状是“*ngFor”似乎没有正确处理流。这很明显,不是吗?

【问题讨论】:

  • 我认为这是问题所在:this.contents$ = this._contentService.contents$;。请在您的模板中尝试此操作:*ngFor="let item of _contentService.contents$ | async"
  • 您能否尝试将这一行 `this.contents$ = this._contentService.contents$;` 移动到构造函数中?我还没有尝试过,但如果contents$null,当它第一次尝试解析绑定时,视图可能不喜欢它。
  • @rinukkusu:组件的支持对象也有一个名为“contents$”的属性。这是我为这个问题命名这些类似的错误。但是,我确实尝试过,直接采购服务。不幸的是,什么都没有。
  • @GünterZöchbauer:好主意。我将它移到构造函数中,但输出是相同的。还是没有骰子。
  • Plunker 会很有帮助

标签: angular rxjs observable


【解决方案1】:

问题在于 Angular 会评估

<h1 *ngFor="let item of contents$ | async">{{ item.name }}</h1>

仅在下次运行更改检测时。

因为

this._service.load();

执行同步,事件在 Angular 有机会订阅之前发出。

例如,如果您使用 BehaviorSubject 而不是 Subject 将最后发出的值发送给新订阅者,那么您将获得所需的行为。

Plunker example

您也可以在调用 this._service.load(); 或调用 this._service.load(); 延迟之前手动调用更改检测
但这取决于您的具体要求。

【讨论】:

  • 太棒了!谢谢你——直到现在我才知道为什么 BehaviorSubject 如此重要;只是我有一种感觉,这是一个热与冷的话题。再次感谢!
【解决方案2】:

我发现您的代码中存在潜在问题:

createContent(item: Content): void {
  this._data.contents$.push(item);
  this._contents$.next(this._data.contents$);
}

我会改用以下内容:

createContent(item: Content): void {
  this._data.contents.push(item); // <----
  this._contents$.next(this._data.contents); // <----
}

【讨论】:

  • “内容/$”太多,呵呵。抱歉,这只是原始问题中的一个错字。我已经更新它以反映我拥有的代码。
猜你喜欢
  • 2016-08-20
  • 1970-01-01
  • 1970-01-01
  • 2016-08-14
  • 2020-11-13
  • 1970-01-01
  • 2016-09-01
  • 2021-11-04
  • 1970-01-01
相关资源
最近更新 更多