Angular 2尝试在服务中实现Observable [英] Angular 2 trying to implement Observables in services
问题描述
我正在尝试使用可观察的方法将数据从一个组件发送到另一个组件.在这里,我正在这样实现可观察的服务...
Im trying to send data from one component to other using observable. Here I'm implementing observable in service like this...
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/RX'
@Injectable()
export class SelectedItemService {
stream1$:Observable<any>;
selectedItem:JSON;
stream1$= new Observable(observer=> setTimeout(() => {
observer.next(this.selectedItem);
}, 3000);)
}
并且我的父组件正在将数据初始化为onselect()中的服务,如下所示:
and my parent Component is initializing data to a service in onselect() like below :
import { Component } from '@angular/core';
import {Http, Headers,Response } from '@angular/http';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import {SelectedItemService} from './selecteditem.service'
@Component({
selector: 'newcomponent',
template:`<p>
</p>
<h2>Your Title: {{nameValue}}</h2>
<ul><li *ngFor="let list of lists">Hello {{ list }}</li></ul>
<form class="ui large form segment">
<h3>Add a Link</h3> <div>
<label for="title">Title:</label>
<input [(ngModel)]="nameValue" placeholder="title" name="Title" >
</div>
<label for="link">Link:</label> <input name="link"></form>
<div class=container *ngFor="let data of dataServer"
[class.selected]="data === selectedItem"
(click)="onSelect(data)">
<div id="myimages">
<a routerLink="/SecondNewCom">
<img src="myBaseurl/{{data.images.image3}}">
</a>
<router-outlet></router-outlet>
</div>
<div class=caption> {{data.productName}} </div>
</div>`,
styleUrls: [`./app/mydoc.css`]
})
export class NewComponent {
nameValue: string;
lists: string[];
url:string;
dataServer:JSON[];
length:number;
selectedItem:JSON;
constructor(private http:Http, public myservice:SelectedItemService) {
this.myservice=myservice;
this.nameValue = "declaredName";
this.url="myBaseurl";
this.lists = ['abc', 'xyz', 'lol'];
this.http.get(this.url).map((res:Response) => res.json())
.subscribe(
data => { this.dataServer = data
this.length=Object.keys(this.dataServer).length},
err => console.error(err),
() => console.log('done')
);}
onSelect(data:JSON):void{
this.selectedItem=data;
this.myservice.selectedItem=data;
}
}
子组件正像这样从订户接收数据...但是显示的数据是不确定的,并且我看到空白屏幕.
and child component is receiving the data from subscriber like this... but the data displayed is undefined and i see blank screen.. Where am i doing wrong...
import {Component,Input} from '@angular/core';
import {SelectedItemService} from './selecteditem.service'
@Component({
selector:'secondcomponent',
template:`<h1> This is second new Component</h1>
<h1>{{UiSelectedItem}}</h1>
`
})
export class SecondComponent{
UiSelectedItem:JSON;
constructor(public mservice:SelectedItemService) {
this.mservice=mservice;
mservice.stream1$.subscribe(value=>this.UiSelectedItem=value);
}
}
推荐答案
您应该使用的是Subject
.如果您曾经使用过Angular的EventEmitter
,则它也是Subject
.对于EventEmitter
,我们通常使用它来将事件从子发布到父
What you should be using is a Subject
. If you have ever used Angular's EventEmitter
, this is also a Subject
. With EventEmitter
we usually use it to publish events from child to parent
@Component({
template: `
<child (textChange)="onTextChange()"></child>
`
})
class ParentComponent {}
class ChildComponent {
@Output() textChange = new EventEmitter();
onClick() {
textChange.emit('new value');
}
}
这是您以前使用过的,这是您需要的发布/订阅模式.有人订阅了该事件,然后有人将其发布.在这里可以使用Subject
.正如我所说的,EventEmitter
是Subject
的子类.
It's you've ever used this before, this is is the publish/subscribe pattern that you need. Someone subscribes to the event, and someone publishes it. This is where we can use Subject
. As I said EventEmitter
is a subclass of Subject
.
但是对于这种情况,香草Subject
可能不够好.原因是事件一旦发出,便永远消失了.如果没有人订阅,则没有任何反应.因此,如果在事件发出后您只订阅了一个小项目,那么您什么也不会得到.很多时候,这是不可接受的.
For this case though, the vanilla Subject
may not be good enough. The reason is that once the event is emitted, it is gone forever. If there was no one subscribed, nothing happens with it. So if it happens that you subscribe just a smidget after the event was emitted, then you get nothing. A lot of times this is unacceptable.
在这种情况下,我们可以使用ReplaySubject
.这种类型的主题使您可以保留可配置大小的缓冲区.因此,如果您在事件发出后立即订阅,您仍然会得到它.
For this case, we can use a ReplaySubject
. This type of subject allows you to keep a buffer with configurable size. So if you subscribe right after the event was emitted you will still get it.
这是一个例子
import { ReplaySubject } from 'rxjs/ReplaySubject';
export class SelectedItemService {
private _selectedItem = new ReplaySubject<string>(1); // buffer size 1
selectedItem$ = this._selectedItem.asObservable();
set selectedItem(item: string) {
this._selectedItem.next(item);
}
}
现在要发布的组件只需设置项目
Now the component that wants to publish just needs to set the item
service.selectedItem = 'new item';
以及订阅组件
service.selectedItem$.subscribe(item => {})
另请参见:
- What are RxJS Subject's and the benifits of using them?
- RxJS docs on Subjects
请参见 柱塞
这篇关于Angular 2尝试在服务中实现Observable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!