Angular5 Observables не работают
В #headerComponent есть поле ввода для моего поиска. Когда пользователь выполняет поиск, поисковый запрос отправляется #websocketsService
к узлу-серверу и возвращает результат в формате JSON.
Этот результат должен вызвать метод #graphComponent
,
Я прочитал, что это хорошая практика, чтобы иметь другой сервис для этого, поэтому я создал #dataService
для этого я обращаюсь к наблюдаемым.
Итак, поток:
headerComponent -> (триггеры) #websocketService -> (поисковый запрос к) node.js-Server -> (результат обратно) #websocketService -> (установить переменную в) #dataService -> (метод триггера) #graphcomponent (с новым данные из #dataService)
Все работает нормально, за исключением того, что я не могу получить метод в #graphComponent
срабатывает.
DATASERVICE
import { Injectable, EventEmitter, Output } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
/**
* This Service is for keep, simple and small Data sharing
* to communicate between components
*/
@Injectable()
export class DataService {
private subject = new Subject<any>();
public setGraphData(data) {
console.log('setGraphData:' + data);
this.subject.next({text: data});
}
public getGraphData(): Observable<any> {
console.log('get graphDataSubject');
return this.subject.asObservable();
}
constructor() { }
}
graphComponent
import { Component, OnInit} from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { Subscription } from 'rxjs/Subscription';
import { DataService } from '../../../services/data/data.service';
import { Observable } from 'rxjs/Observable';
@Component({
selector: 'graph',
templateUrl: './graph.component.html',
styleUrls: ['./graph.component.scss'],
providers: [DataService]
})
export class GraphComponent implements OnInit{
graphData: Observable<any>;
subscription: Subscription;
constructor( private _dataService: DataService ) { }
ngOnInit() {
this._dataService.getGraphData().subscribe(graphData => {
console.log('PLEASE TRIGGER ME WHEN graphData IS UPDATED');
});
}
// PLEASE TRIGGER THIS FUNCTION WHEN NEW graphData IS SET
triggerMe() {
console.log('WORKS')
}
}
websocketService
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { DataService } from '../data/data.service';
@Injectable()
export class WebsocketsService {
private _search: string;
private url: string;
public wsConnection: WebSocket;
constructor(private _dataService: DataService) {
this.url = 'ws://localhost:1337';
}
/*
* creates connection, sends query and maps ws-handler
*/
sendQuery(search: string) {
this._search = search;
console.log('Perform search for: ' + this._search);
this.wsConnection = new WebSocket(this.url);
this.wsConnection.onopen = () => this.wsConnection.send(JSON.stringify({ data: this._search }));
this.wsConnection.onerror = event => console.log('A Error has occured!');
this.wsConnection.onclose = event => console.log('Connection closed');
this.wsConnection.onmessage = (event) => {
// SEND NEW DATA TO OBSERVABLE
this._dataService.sendGraphData(event.data);
};
}
}
Я просто не могу запустить его, что когда новый graphData
устанавливается в #dataService, triggerMe()
в #graphComponent срабатывает.
1 ответ
Проблема в том, что вы назначаете Observable для Observable.
graphData
в вашем сервисе данных есть Observable, а в вашем компоненте вы устанавливаете свойство viewmodel graphData
, который также является наблюдаемым, к наблюдаемому, возвращенному службой.
Вместо этого вам нужно установить тип значения viewmodel равным тому, что собирается вернуть websocket, например string
или же object
или напихать и использовать any
,
Я изменил несколько имен и создал для этого пример проекта. Вот ссылка на исходный код: https://1drv.ms/u/s!Aun50jHsxPB0gcd4emGcDqViLGbySw
Служба данных остается неизменной, но я изменил службу сокетов, чтобы включить службу эха в Интернете для демонстрации:
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { DataService } from './data.service';
@Injectable()
export class SocketService {
public wsConnection: WebSocket;
url: string;
constructor(private _dataService: DataService) {
this.url = 'ws://echo.websocket.org/';
}
/*
* creates connection, sends query and maps ws-handler
*/
sendQuery(): void {
this.wsConnection = new WebSocket(this.url);
this.wsConnection.onopen = () => this.wsConnection.send('Test Message');
this.wsConnection.onerror = event => console.log('A Error has occured!');
this.wsConnection.onclose = event => console.log('Connection closed');
this.wsConnection.onmessage = (event) => {
this._dataService.setGraphData(event.data);
};
}
}
Я просто использовал app.component.ts, созданный Angular CLI в этом примере компонента, чтобы получить значение от сервиса:
import { Component, OnInit, OnDestroy} from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { Subscription } from 'rxjs/Subscription';
import { DataService } from './data.service';
import { SocketService } from './socket.service';
@Component({
selector: 'app-root',
template: `
Graph Data: {{ data }}
`,
})
export class AppComponent implements OnInit, OnDestroy {
data: any; // <-- not an Observable
subscription: Subscription;
constructor (
private dataService: DataService,
private socketService: SocketService,
) {}
ngOnInit() {
// Get the data from the socket service
this.socketService.sendQuery();
this.subscription = this.dataService.getGraphData().subscribe(graphData => {
// set the value in the viewmodel with the data from the service
this.data = graphData.text;
});
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
}
Сначала установите зависимости, затем запустите пример кода с помощью: ng serve
и вы увидите значение, возвращаемое сервисом.