[英]Angular2 shared observable
Doing some experimentation with Angular2 and curious about how to solve a situation where a service exposes a shared observable. 对Angular2进行了一些试验,并对如何解决服务公开共享的可观察对象的情况感到好奇。 Where one component is responsible for getting the data and another is responsible for displaying the data.
其中一个组件负责获取数据,另一个组件负责显示数据。 Here is some code:
这是一些代码:
The common HttpService responsible for getting the data 负责获取数据的通用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);
}
}
The GetComponent responsible for getting the data 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();
}
}
The DisplayComponent responsible for displaying the data 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();
}
}
This design works ok except the error handling does not work for the DisplayComponent
. 除错误处理不适用于
DisplayComponent
之外,此设计可以正常进行。 Also the map function in the HttpService
doesn't seem quite right this.subject.next(res.json()
另外
HttpService
中的map函数看起来不太正确this.subject.next(res.json()
Also it doesn't seem quite right that the GetComponent has to "subscribe" like this this.service.get(this.url).subscribe();
同样,GetComponent不得不像这样this来“订阅”似乎也不是正确的。service.get
this.service.get(this.url).subscribe();
What is the proper way to design this sort of thing? 设计此类事物的正确方法是什么? How can I get the
DisplayComponent
to observe errors thrown by the HttpComponent
如何获取
DisplayComponent
来观察HttpComponent
引发的错误
Your code has several problems where Service.$observable is modified several times: 您的代码有几个问题,其中Service。$ observable被多次修改了:
observable$ = this.subject.asObservable();
this.observable$ = this.http.get('myapi.com') .... // remove this line
The right way to do this: Get Component
calls Service
to get data. 正确的方法:
Get Component
调用Service
以获取数据。 After data is loaded, Get Component
emits a Data Ready
event with the data. 加载数据后,“
Get Component
将与数据一起发出“ Data Ready
事件。 Display Component
, and other components that use this data, listen to DataReady
event and update data when the event is emitted. Display Component
以及使用此数据的其他组件,侦听DataReady
事件并在事件发出时更新数据。
Code to explain my answer: 代码来解释我的答案:
@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
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.