Angular 2尝试在服务中实现Observable [英] Angular 2 trying to implement Observables in services

查看:98
本文介绍了Angular 2尝试在服务中实现Observable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用可观察的方法将数据从一个组件发送到另一个组件.在这里,我正在这样实现可观察的服务...

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.正如我所说的,EventEmitterSubject的子类.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆