角度-为什么要订阅?为什么不直接在组件中使用服务的属性?

时间:2018-08-19 15:10:03

标签: angular rxjs angular6

在任何地方,您都可以看到subscribe here, subscription there, unsubscribe here, unsubscribe there。我问,如果可以在组件中直接使用服务属性,我们需要这些样板代码做什么?

@injectable()
export class MyService {
  public logItems: Log[] = [];

  getLatestLogItems() {
      return this.httpService.GetLatestLogItems() // some http service
      .subscribe(
          (items) => {
              this.logItems = items;
          },
          ...
      );
  }
}

,然后在组件中:

@Component({
  selector: 'app-logs',
  template:    `<ul>
                 <li *ngFor="let log of myService.logItems"> {{ log | json}} </li>
               </ul> `
})
export class MyComponent implements OnInit {
  constructor(public myService: MyService) { }

  ngOnInit() {
    this.myService.getLatestLogItems();
  }

如果要刷新数据,只需再次调用getLatestLogItems()。 我在这里想念什么?为什么根本需要学科?

4 个答案:

答案 0 :(得分:0)

您应该订阅组件并从服务中返回可观察到的

@injectable()
export class MyService {
  public logItems: Log[] = [];

  getLatestLogItems(): Observable<any> {
      return this.httpService.GetLatestLogItems() // some http service
  }
}

在组件中:

 ngOnInit() {
    this.myService.getLatestLogItems().subscribe(response => {console.log(response)})
  }

答案 1 :(得分:0)

可观察到的ReactiveX

要解决此问题,您需要了解ObservableObserver的概念。

Observables不返回任何内容,而是发出项目,以便Observers可以订阅。这样Observer随时准备在Observable将来的任何时间做出适当的反应。

有关更多信息,请参阅ReactiveX documentation

是的,订阅和取消订阅有时看起来很令人沮丧,但是在您的代码中:

  getLatestLogItems() {
       return this.httpService.GetLatestLogItems().subscribe((items) => {
                   this.logItems = items;
               });
  }

getLatestLogItems不返回任何内容。

答案 2 :(得分:0)

根据您的用例,通常我认为做上面提到的方式是一个坏主意:

  1. 潜在的内存泄漏:何时取消订阅?反复调用getLatestLogItems可能会导致内存泄漏。虽然在这种情况下,可能不是因为httpClient处理了此问题,但是其他可以观察到的方法也可能。

  2. 值更新未跟踪:您的myService.logItems值未跟踪。如果您在同一页面中有多个相同的组件(例如ngFor),或者在其他页面中使用了该组件+您的服务是单例的(大多数情况下是这样),则可能会导致意外结果。在此处查看简单的演示:https://stackblitz.com/edit/so-rxjs-test。该值未在模板中正确更新。

  3. 关注点分离:服务应在组件中是私有的。您正在向公众公开服务。这不是一个好习惯。这是因为服务(另一层)用于代码分离。如果您按照上述方式操作,则不妨直接在组件中编写getLatestLogItems函数。

  4. 如果您不喜欢样板代码,则可以考虑通过调用observable将所有promise转换为.toPromise。这样,您无需.subscribe.unsubscribe,但您需要.thenasync await ...

我希望这为样板提供了一些理由。如果您正在使用其他框架(例如React或Vue),甚至只是没有rxjs的jquery,则对于所有api调用,项目4都是不可避免的(需要.then或异步等待)。

答案 3 :(得分:0)

我不会说您的代码是错误的。 Http请求会自动退订,因此不会出现内存泄漏。您还可以控制何时发生请求。在代码方面,我看不到任何问题,但也许我遗漏了一些东西。

我仍然不会使用此模式。我的观点是服务将开始定义您的组件。感觉有点奇怪。您还限制了RxJ的使用。每个组件都应按其认为适合该特定组件的方式处理api调用。

但是,我没有看到任何功能上的损失,但是我确实看到黑客入侵了您的代码。因此,这并不可怕,但是在服务方面却有点自私。让组件决定如何使用数据。