Angular2共享可观察

时间:2016-08-28 23:27:38

标签: reactjs angular typescript reactive-programming rxjs

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

负责获取数据的常见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();
  }
}

此设计正常,但错误处理不适用于DisplayComponentHttpService中的地图功能似乎也不对this.subject.next(res.json()

同样,GetComponent必须&#34;订阅&#34;像这样this.service.get(this.url).subscribe();

设计这类东西的正确方法是什么?如何让DisplayComponent观察HttpComponent

引发的错误

1 个答案:

答案 0 :(得分: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
  }
}