如何在Angular 2/5中订阅服务对象?

时间:2017-12-29 18:40:11

标签: javascript angular typescript angular2-services

我有问题,我希望在来自服务器之后将数据接收到我的属性组件中。

我在服务中做了类似的事情:

private events: Event[] = [];
eventChanged = new Subject<any>(); // Edit: added an observable

constructor(private http: HttpClient) { 
    this.http.get<Event[]>(this.baseUrl)
    .subscribe(events => this.events = events);
  this.eventChanged.next(this.events.slice()); //Edit: added an information to subscribers that events list changed
}
getEvents(): Observable<Event[]> {
    return this.eventChanged.asObservable();
}  // Edit: now I use this method to enables subscribers to observable

        /* I don't use that method after Edit
        showAllEvents(): Event[] {
            return [...this.events];
        }
        */

然后我将方法showAllEvents()用于我的组件:

private events: Event[] = [];
private calendarEvents: CalendarEvent[] = [];
subscription: Subscription; // Edit: Added a Subscription

    getInterestedEvents() {
       // this.events = this.el.showAllEvents(); <-- I changed it into observable
   this.subscription = this.el.getEvents()
    .subscribe(
    (events) => {
      this.events = events;
    });
    this.events.forEach(eachEvent => {
        let calendarEvent: CalendarEvent = {
            start: subDays(startOfDay(new Date()), 1),
            end: addDays(new Date(), 1),
            title: eachEvent.name,
            color: colors.red
        }
        this.calendarEvents.push(calendarEvent);
    })
}

我不知道如何让this.events等待来自服务的数据。有任何想法吗?在每一页上看起来都不一样,现在我觉得自己像个傻瓜。

修改

我进行了订阅和观察,但仍然this.el.getEvents().subscribe...在我的组件中返回任何数据。

2 个答案:

答案 0 :(得分:5)

您可以在服务中创建订阅,以通知事件列表是否已更改

eventChanged = new Subject<Event[]>();
在您的组件中

,如果事件列表已更改,您将要订阅eventChanged

this.subscription = this.eventService.eventChanged
  .subscribe(
    (event: Event[]) => {
      this.events = events;
    }
  );

然后在您的服务中添加next,以便在每次任何组件更新时通知事件已更改,并使其重新发送事件列表或任何您想要的内容

  addEvent(event: Event) {
    this.events.push(event);
    this.eventChanged.next(this.events.slice());
  }

更新:使用示例

如果我们有事件查看器,事件编辑器组件和事件服务

设置事件服务以使主题(事件已更改),访问者(获取事件)加法器(更新事件)

import { Injectable } from '@angular/core';
import {Subject} from 'rxjs/Subject';

@Injectable()
export class EventService {

  eventChanged = new Subject<string[]>();

  events: string[] = [
    'Pizza Party',
    'Hackacthon',
    'Movie Night'
  ]
  constructor() { }

  addEvent(event: string) {
    this.events.push(event);
    this.eventChanged.next(this.events.slice());
  }

  getEvents() {
    return this.events.slice();
  }
}

然后组件EventViewer获取列表,并订阅任何更改

<强>事件viewer.component.ts

import { Component, OnInit } from '@angular/core';
import {EventService} from '../event.service';
import {Subscription} from 'rxjs/Subscription';

@Component({
  selector: 'app-event-viewer',
  templateUrl: './event-viewer.component.html',
  styleUrls: ['./event-viewer.component.css']
})
export class EventViewerComponent implements OnInit {

  subscription: Subscription;
  events: string[] = this.eventService.getEvents();

  constructor(private eventService: EventService) { }


  ngOnInit() {
    this.subscription = this.eventService.eventChanged
    .subscribe(
      (events: string[]) => {
        this.events = events;
      }
    )
  }

}

然后我们将其渲染出来

<强>事件viewer.component.html

<ul>
  <li *ngFor="let event of events">{{event}}</li>
</ul>

最后我们想要一个事件编辑器组件

事件editor.component.ts

import { Component, OnInit } from '@angular/core';
import {EventService} from '../event.service';

@Component({
  selector: 'app-event-edit',
  templateUrl: './event-edit.component.html',
  styleUrls: ['./event-edit.component.css']
})
export class EventEditComponent implements OnInit {

  eventNumber: number = 1;

  constructor(private eventService: EventService) { }

  ngOnInit() {
  }

  addEvent()
  {
    this.eventService.addEvent(this.eventNumber.toString())
    this.eventNumber++;
  }

}

并呈现一个供用户控制的按钮

事件editor.component.ts

<button (click)="addEvent()">Add event {{eventNumber}}</button>

在选择的模块中,我们显然必须声明这些组件,登记提供者

<强> app.module.ts

@NgModule({
  declarations: [
    EventViewerComponent,
    EventEditComponent
  ],
  imports: [
    CommonModule
  ],
  providers: [EventService]
})

然后在那时我们渲染两个组件

app.component.ts

<app-event-viewer></app-event-viewer>
<app-event-edit></app-event-edit>

现在,每当我们点击一​​个组件中的按钮时,另一个组件就会获得更新列表 enter image description here

答案 1 :(得分:0)

例如:

export class YourService {
    private refreshSource: Subject<boolean> = new Subject();
    public refreshStream: Observable<boolean> = this.refreshSource.asObservable();

    endpoint_url = "https://<your_backend>/api/";

    constructor(private client: HttpClient) {}

    // get collection
    cget(queryParams: any): Promise<Obj[]> {
         return this.client.get<Obj[]>(this.endpoint_url + 'objs').toPromise();
    }

    // create one object
    post(obj: Obj): Promise<Obj> {
        const res = this.client.post(
            this.endpoint_url + 'objs',
            JSON.stringify(obj),
            this.requestParams);

        return res.toPromise().then((response) => {
            obj.id = response['id'];
            this.refreshSource.next(true);
            return obj as Obj;
        });
}



export class YourComponent implements OnDestroy {
    subscriptions: Subscription[] = [];
    success:boolean;
    failure:boolean;
    loading:boolean;

    constructor(private ys: YourService) {
        this.subscriptions.push( this.ys.refreshStrem.subscribe(() => this.load()) );
    }


    async load() {
        this.yourObjs = await this.ys.cget();
    }

    async submit() {
        this.loading = true;
        try {
            const response = this.ys.post(this.obj)
            this.success = true;   
        } catch (error) {
            console.log('error', error);
            this.failure = true;
        } finally {
            this.loading = false;
        }
    }

    ngOnDestroy() {
        this.subscriptions.forEach(subscription => subscription.unsubscribe());

}