Невозможно обновить список в Angular 2 с помощью Observable

Я использую angular 2 и socket.io вместе для загрузки данных и перезагрузки изменений с помощью socket.io

У меня есть сервис для загрузки данных из API:

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
import * as io from 'socket.io-client';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { Call } from '../model/call';
import * as globals from '../../globals';

@Injectable()
export class CallService {

  private socket;

  constructor(private http: Http) { }

    /**
     * Load all calls data from server.
     * @method loadCalls
     *
     * @return {Observable<Call[]>}
     */
  loadCalls(): Observable<Call[]> {
    return this.http
      .get(globals.server + globals.apiRoutes['calls'])
      .map(res => {
        return res.json();
      });
  }

  /**
   * Observer for call's mission time changing
   * @method callObserver
   * @return {Observable<any>}
   */
  callObserver() :Observable<any>{
    let observable = new Observable(observer => {
      this.socket = io.connect(globals.socketioServer);
      this.socket.on('call-channel:App\\Events\\CallEvent' , data => {
        observer.next(data);
      });
      return () => {
        this.socket.disconnect();
      }
    });
    return observable;
  }

}

Метод loadCalls загружает данные всех вызовов при запуске приложения, а метод callObserver прослушивает любые широковещательные изменения с сервера. Файл call-component.ts:

import { Component, OnInit, OnDestroy ,Input} from '@angular/core';
import * as io from 'socket.io-client';
import { CallService } from './service/call.service';
import { Call } from './model/call';
import { Observable } from 'rxjs/Observable';

@Component({
  selector: 'app-call-status',
  templateUrl: './call-status.component.html',
  styleUrls: ['./call-status.component.css'],
  providers: [
    CallService,
  ],
})
export class CallStatusComponent implements OnInit, OnDestroy  {

  private connection;

  private calls: Call[] = new Array();

  private noMissionCalls: Call[] = new Array();

  private backToBaseCalls: Call[] = new Array();

  private finishMissionCalls: Call[] = new Array();

  private deliveredpatientCalls: Call[] = new Array();

  private arriveHospitalCalls: Call[] = new Array();

  private moveFromCalls: Call[] = new Array();

  private arrivedCalls: Call[] = new Array();

  private startMissionCalls: Call[] = new Array();

  private notifyMissionCalls: Call[] = new Array();

  constructor(private callService: CallService) {

  }

  ngOnInit() {

    this.classifyCalls(); //load calls data

    //listen for changes from server
    this.connection = this.callService.callObserver().subscribe(function(res) {
      let call: Call = res.data ? res.data[0] : null;
      if (call) {
        console.log(call);
      }

    });


  }

  ngOnDestroy() {
    this.connection.unsubscribe();
  }


  classifyCalls() {

    this.calls = new Array();
    this.noMissionCalls = new Array();
    this.backToBaseCalls = new Array();
    this.finishMissionCalls = new Array();
    this.deliveredpatientCalls = new Array();
    this.arriveHospitalCalls = new Array();
    this.moveFromCalls = new Array();
    this.arrivedCalls = new Array();
    this.startMissionCalls = new Array();
    this.notifyMissionCalls = new Array();

    this.callService.loadCalls().subscribe(calls =>{
      for(let item of calls){
        this.classifySingleCall(item);
      }
    });
  }

  classifySingleCall(call: Call) {
    if (call.mission_times == null) {
      call.status_name = 'noMissionCalls'
      this.noMissionCalls.push(call);

    } else if (call.mission_times.back_base) {
      call.status_name = 'backToBaseCalls';
      this.backToBaseCalls.push(call);

    } else if (call.mission_times.finish_mission) {
      call.status_name = 'finishMissionCalls';
      this.finishMissionCalls.push(call);

    } else if (call.mission_times.deliver_patient) {
      call.status_name = 'deliveredpatientCalls';
      this.deliveredpatientCalls.push(call);

    } else if (call.mission_times.arrive_hospital) {
      call.status_name = 'arriveHospitalCalls';
      this.arriveHospitalCalls.push(call);

    } else if (call.mission_times.move_from) {
      call.status_name = 'moveFromCalls';
      this.moveFromCalls.push(call);

    } else if (call.mission_times.arrived_urgency) {
      call.status_name = 'arrivedCalls';
      this.arrivedCalls.push(call);

    } else if (call.mission_times.start_mission) {
      call.status_name = 'startMissionCalls';
      this.startMissionCalls.push(call);

    } else if (call.mission_times.notify_mission || call.mission_times.get_message) {
      call.status_name = 'notifyMissionCalls';
      this.notifyMissionCalls.push(call);

    } else {
      call.status_name = 'noMissionCalls';
      this.noMissionCalls.push(call);
    }

    return call;
  }


}

Загрузка данных производится при запуске приложения. Но проблема здесь: когда изменение вызова передается всем клиентам, я могу получить данные этого вызова, используя этот код, который помещается в ngOnInit()

 this.connection = this.callService.callObserver().subscribe(function(res) {
      let call: Call = res.data ? res.data[0] : null;
      if (call) {
        console.log(call);//log the call

        console.log(this.calls);//undefined
      }

    });

Но я не могу получить доступ к данным this.calls в операторе if кода. Данные вызовов загружаются в первую строку ngOnInit. Как я могу получить доступ к данным, заполненным методом this.classifyCalls();?


person M Gholami    schedule 26.12.2016    source источник


Ответы (1)


Не используйте слово function внутри классов при использовании машинописного текста. Это заменяет this контекст класса контекстом функции, которую вы только что определили. Используйте обозначение стрелки:

this.connection = this.callService.callObserver().subscribe((res) => { //<-- here
   let call: Call = res.data ? res.data[0] : null;
   if (call) {
      console.log(call);//log the call
       console.log(this.calls);//undefined
   }

});
person Poul Kruijt    schedule 26.12.2016
comment
Я делаю это, но undefined меняется на пустой массив - person M Gholami; 26.12.2016
comment
Ну.. Что еще вы ожидаете? Вы инициируете его как пустой массив и ничего в него не вставляете. Он должен быть пуст :). Вы только отправляете «вызовы» в другие массивы - person Poul Kruijt; 26.12.2016
comment
Яаааа! вы правы! Я делаю слишком много изменений в коде! И заполнение массива вызовов удалено из моего кода. Но с вашей помощью для использования функции стрелки я могу получить доступ к вызовам. До этого он возвращает мне undefined. Танки мальчик!!!! - person M Gholami; 26.12.2016