Просто для некоторого контекста у меня есть следующее:
Внутренняя служба (Kotlin), которая генерирует поток данных:
@GetMapping(value = ["api/v2/stocks"], produces = [MediaType.TEXT_EVENT_STREAM_VALUE])
fun fromMongo(): Flux<MutableList<Stock>> {
return Flux.interval(Duration.ZERO, Duration.ofSeconds(5))
.flatMap { stockService.getAllStocks().collectList() }
}
Служба angular для обработки сервера отправленные события:
export class StockService {
uri = 'http://localhost:8081';
stocks: Observable<Stock>
constructor(private http: HttpClient, private sseService: SseServiceService, private zone: NgZone) { }
getStocks(): Observable<Stock> {
return this.http.get<Stock>(`${this.uri}/api/v2/stocks`)
}
getStocksSSE(): Observable<Stock> {
return Observable.create(observer => {
const eventSource = this.sseService.getEventSource(`${this.uri}/api/v2/stocks`);
eventSource.onmessage = event => {
this.zone.run(() => {
observer.next(JSON.parse(event.data));
});
}
eventSource.onerror = error => {
this.zone.run(() => {
console.log(error)
observer.error(error);
})
}
});
}
getStockBySymbol(symbol: string): Observable<Stock> {
return Observable.create(observer => {
const eventSource = this.sseService.getEventSource(`${this.uri}/api/v2/stocks/${symbol}`);
eventSource.onmessage = event => {
this.zone.run(() => {
observer.next(JSON.parse(event.data));
})
}
eventSource.onerror = error => {
this.zone.run(() => {
observer.error(error);
})
}
});
}
Наконец, компонент для отображения полученных данных:
export class StockListComponent implements OnInit {
stocks: Observable<Stock>
displayedColumns: String[] = ['symbol', 'name', 'value', 'gains', 'details', 'buy'];
constructor(private router: Router,
private stockService: StockService) {}
ngOnInit(): void {
this.stocks = this.stockService.getStocksSSE();
}
}
Связанный компонент. html:
<mat-card>
<div class="mat-table-data">
<table mat-table #table [dataSource]="stocks" aria-label="Stocks">
<ng-container matColumnDef="symbol">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Symbol</th>
<td mat-cell *matCellDef="let row">{{row.symbol}}</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
<td mat-cell *matCellDef="let row">{{row.name}}</td>
</ng-container>
<ng-container matColumnDef="value">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Share Price</th>
<td mat-cell *matCellDef="let row">£ {{row.value}}</td>
</ng-container>
<ng-container matColumnDef="gains">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Change</th>
<td mat-cell *matCellDef="let row">
<div class="green" *ngIf="row.isPositive==true">
+{{row.gains}}
</div>
<div class="red" *ngIf="row.isPositive==false">
{{row.gains}}
</div>
</td>
</ng-container>
<ng-container matColumnDef="details">
<th mat-header-cell *matHeaderCellDef>See More</th>
<td mat-cell *matCellDef="let element">
<button mat-button routerLink="/stocks/{{element.symbol}}">Details</button>
</td>
</ng-container>
<ng-container matColumnDef="buy">
<th mat-header-cell *matHeaderCellDef>Purchase</th>
<td mat-cell *matCellDef="let element">
<button mat-button routerLink="/stocks/{{element.symbol}}">Buy</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
</mat-card>
Странное поведение, которое я вижу, состоит в том, что если я перемещаюсь между компонентами три раза (всегда конкретно три) и возвращаюсь к компоненту, где можно увидеть список акций, данные не загружаются в таблицу angular. Следует отметить, что до этого все работало, как и ожидалось, и, во-вторых, если бы я был console.log(observer.next(JSON.parse(event.data)));
в сервисе, я все равно видел все данные в консоли, как и ожидалось. Это приводит меня к мысли, что проблема лежит где-то с ng-dataSource.
Открыто для всех предложений!