Angular 7 EventSource keeps fetching the stream indefinitely

I'm using Spring Webflux on my server-side to return a Flux of objects. When I access the endpoint via the browser it works as expected, I get the 5 objects then the stream stops.

However when attempting to do it via Angular EventSource the stream seems stuck on 'repeat' for lack of a better word. How do I tell the EventSource to stop requesting more items when they've all been sent from the server?

The code is simple, but I've never used Angular for event sourcing before.

Service:

@Injectable({providedIn: 'root'})
export class VideoSourceService {

  private videoDataSource: BehaviorSubject<Array<Video>> = new BehaviorSubject([]);

  videoData = this.videoDataSource.asObservable();

  startVideoStream(source: string) {
    const eventSource = new EventSource(source + "/videos");

    eventSource.addEventListener('message', message => {
      this.videoDataSource.next([...this.videoDataSource.value, JSON.parse(message["data"])]);
    });
  }

Consumer:

@Component({
  selector: 'app-videos',
  templateUrl: './videos.component.html',
  styleUrls: ['./videos.component.scss']
})
export class VideosComponent implements OnInit {
  videos$: Observable<Video[]>;

  constructor(public videoSourceService: VideoSourceService) {

  }

  ngOnInit(): void {
    this.videoSourceService.startVideoStream(`${environment.apiUrl}`);

    this.videos$ = this.videoSourceService.videoData;
  }
}

and just for completeness, my backend method:

@GetMapping(value = "videos", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Video> getVideos() {

    return videoRepository.findAll();
}

As the backend works as expected in Chrome, I'm assuming the issue is somewhere with my Angular code?

1 answer

  • answered 2019-04-15 06:15 Chris Turner

    Turns out it was a simple issue, you need to manually close the connection when you're done with it.

      startVideoFavoriteStream(source: string) {
        //{...}
    
        eventSource.onerror = () => {
            eventSource.close();
        }
      }
    

    does the trick.