对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();
}
}
此设计正常,但错误处理不适用于DisplayComponent
。 HttpService
中的地图功能似乎也不对this.subject.next(res.json()
同样,GetComponent必须&#34;订阅&#34;像这样this.service.get(this.url).subscribe();
设计这类东西的正确方法是什么?如何让DisplayComponent
观察HttpComponent
答案 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
}
}