【问题标题】:Angular2 shared observableAngular2 共享 observable
【发布时间】:2017-01-04 22:07:14
【问题描述】:

正在使用 Angular2 进行一些实验,并对如何解决服务公开共享可观察对象的情况感到好奇。一个组件负责获取数据,另一个组件负责显示数据。这是一些代码:

负责获取数据的常用HttpService

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class Service {

  subject = new Subject<string[]>;

  observable$ = this.subject.asObservable();

  constructor(private http: Http) {}

  observable: Observable<string[]>;

  get(link: string): Observable<string[]> {
    this.observable$ = this.http.get('myapi.com')
                    .map((res: Response) => this.subject.next(res.json())
                    .catch(this.handleError);

    return this.observable$;
  }

  /**
    * Handle HTTP error
    */
  private handleError (error: any) {
    // In a real world app, we might use a remote logging infrastructure
    // We'd also dig deeper into the error to get a better message
    let errMsg = (error.message) ? error.message :
      error.status ? `${error.status} - ${error.statusText}` : 'Server error';
    console.error(errMsg); // log to console instead
    return Observable.throw(errMsg);
  }
}

负责获取数据的GetComponent

import { Component, OnInit, OnDestroy } from '@angular/core';

import { Service } from '../shared/index';


@Component({
  moduleId: module.id,
  selector: 'get',
  templateUrl: 'get.component.html',
  providers: [Service],
})
export class GetComponent {

  constructor(public service: Service) {}

  submit() {
    this.service.get(this.url).subscribe();
  }
}

负责显示数据的DisplayComponent

import { Component, OnInit, OnDestroy } from '@angular/core';

import { Subscription } from 'rxjs/Subscription';


@Component({
  moduleId: module.id,
  selector: 'display',
  templateUrl: 'display.component.html'
})
export class DisplayComponent {
  subscription: Subscription;

  constructor(public service: Service) {}

  ngOnInit() {
    // the observable is undefined :(
    this.subscription = this.service.observable$.subscribe(data => {
      console.log(data);
    },
    error => {
      // this never gets reached :(
    })
  }
  ngOnDestroy() {
    // prevent memory leak when component is destroyed
    this.subscription.unsubscribe();
  }
}

除了错误处理不适用于DisplayComponent,此设计工作正常。 HttpService 中的地图功能也不太正确this.subject.next(res.json()

此外,GetComponent 必须像这样this.service.get(this.url).subscribe();“订阅”似乎不太正确

设计这种东西的正确方法是什么?如何让DisplayComponent 观察HttpComponent 引发的错误

【问题讨论】:

    标签: reactjs angular typescript reactive-programming rxjs


    【解决方案1】:

    你的代码有几个问题,Service.$observable 被多次修改:

    observable$ = this.subject.asObservable();
    this.observable$ = this.http.get('myapi.com') .... // remove this line
    

    执行此操作的正确方法: Get Component 调用 Service 来获取数据。加载数据后,Get Component 会发出带有数据的 Data Ready 事件。 Display Component 和其他使用此数据的组件会监听 DataReady 事件并在事件发出时更新数据。

    解释我的答案的代码:

    @Injectable()
    export class GetService {
      /// subject
      subject = new Subject<string[]>()
    
      /// the observable
      observable = this.subject.asObservable()
    
    
      constructor(private $http: Http) {
    
      }
    
      /// get data
      getData() {
        // not override observable here
        this.$http.get("api.com")
          .map(response => response.json()) // map the data
          .subscribe((data: string[]) => this.subject.next(data), // emit data event
                  error => this.subject.error(error)) // emit error event
      }
    }
    

    【讨论】:

    • 事件?我想使用 RxJS。
    • 是的,除了你将 $observable 从 this.subject.asObservable() 修改为 this.http.get('myapi.com') 并且你没有将错误重定向到 this.subject.asObservable() 之外,你的代码是正确的
    • 哦,我尝试在 HttpService 捕获函数中执行 this.subject.error(error)。您可以在建议的解决方案的答案中添加一些代码吗?
    • 我也尝试只返回 this.http.get('myapi.com') 而不是重置 this.observable$,这可能是个坏主意
    • 所以你是说我应该返回一个订阅而不是一个 Observable?
    猜你喜欢
    • 2018-01-27
    • 1970-01-01
    • 2017-10-08
    • 1970-01-01
    • 1970-01-01
    • 2017-06-20
    • 2018-01-04
    • 1970-01-01
    • 2016-08-06
    相关资源
    最近更新 更多