简体   繁体   中英

Angular and receiving stream from api

I am trying to receive from Web.API a event stream using angular 6 version so my API method looks simple enaught:

    [HttpGet, ActionName("GetValues")]
    public async Task GetValues()
    {
        try
        {
            //Get values from db

            Response.Headers.Add("Content-Type", "text/event-stream");
            foreach (var value in values)
            {
                string jsonResponse = JsonConvert.SerializeObject(value);
                byte[] dataItemBytes = Encoding.ASCII.GetBytes(jsonResponse);
                await Response.Body.WriteAsync(dataItemBytes,0, dataItemBytes.Length);
                await Response.Body.FlushAsync();
            }
        }
        catch (Exception ex)
        {
            logger.Error(ex);
        }
    } 

So now I was trying to use something like:

return this.httpClient.get<any>(http://localhost/api/System/GetValues`);

And all that I am receiving is

Http failure during parsing for https://localhost/api/System/GetValues

So idea is I am sending request and reviving stream (stream will transfer lots of data that's why I used it) in return, it works on swagger and it also works on postman. But I am having problem with angular, what can I do?

try with specifying responseType: 'text'

this.httpClient.get<any>(http://localhost/api/System/GetValues`, 
     { ...options, responseType: 'text' });

HttpClient.get() expects a single response, and that's not what your method is sending. Server Side Events are handled a little bit differently in JavaScript - check EventSource docs in MDN .

By following a simple, nice implementation example (that runs everything within NgZone) from here :

import { Injectable, NgZone } from "@angular/core";
import { Observable } from "rxjs";
@Injectable({
  providedIn: "root"
})
export class SseService {
  constructor(private _zone: NgZone) {}
  getServerSentEvent(url: string): Observable<any> {
    return Observable.create(observer => {
      const eventSource = this.getEventSource(url);
      eventSource.onmessage = event => {
        this._zone.run(() => {
          observer.next(event);
        });
      };
      eventSource.onerror = error => {
        this._zone.run(() => {
          observer.error(error);
        });
      };
    });
  }
  private getEventSource(url: string): EventSource {
    return new EventSource(url);
  }
}

This creates a nice wrapper for handling SSE - you can use it as a equivalent of httpClient.get():

this.sseService
  .getServerSentEvent("http://localhost/api/System/GetValues")
  .subscribe(data => console.log(data));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM