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

How to subscribe object from service in Angular 2/5?

我有问题,我想在 属性 组件中接收来自服务器的数据。

我在服务中做了这样的事情:

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... 没有 return 我的组件中的任何数据。

您可以在您的服务中创建一个订阅,以在事件列表发生变化时发出通知

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>

现在每次我们点击一​​个组件中的按钮时,另一个组件都会获得更新的列表

例如:

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());

}