What determines the Angular zone with Socket IO

Viewed 93

I ran into an interesting problem with using SocketIO in my Angular Service.

Case 1: Socket as a property of the service
When I instantiate the socket on the service class all responses from the socket are done in the angular zone and the UI will update accordingly.

import { io } from 'socket.io-client/build/index';
import { Injectable, NgZone } from '@angular/core';

@Injectable() {
export class MyService {
  private socket = io("localhost:3000")
  
  dealCards(): void {
    this.socket.emit('deal_cards')
  }

  recieveStartingCards(): Observable<GameState> {
    const observable = new Observable<GameState>((observer) => {
      this.socket.on('dealt_cards', (data: GameState) => {
        console.log('IN ZONE', NgZone.isInAngularZone()); // returns true
        observer.next(data));
        return () => this.socket.disconnect();
      });
    });
    return observable;
  }

Case 2: Socket as a constant
When I instantiate the socket as a constant and reference it in the service class. The socket communication occurs outside the angular zone and the UI will only update if you I use ngZone.run()

import { io } from 'socket.io-client/build/index';
import { Injectable, NgZone } from '@angular/core';

const socket = io("localhost:3000")

@Injectable() {
export class MyService {
  constructor(private ngZone: NgZone) {}
  private socket = socket
  dealCards(): void {
    this.socket.emit('deal_cards')
  }

  recieveStartingCards(): Observable<GameState> {
    const observable = new Observable<GameState>((observer) => {
      this.socket.on('dealt_cards', (data: GameState) => {
        console.log('IN ZONE', NgZone.isInAngularZone()); // returns false
        observer.next(data));
        return () => this.socket.disconnect();
      });
    });
    return observable;
  }

My question is why is socket communication in Case 1 always in the Angular zone and why is socket communication in Case 2 never in the angular zone?

1 Answers

Angular zone comes into play at the stage of bootstrapping Angular application. All Angular services, which are involved in DI(Dependency Injection) system, are instantiated inside this NgZone.run call.

In the first case you use socket as a property. It means that it will be instantiated inside service constructor and it happens after bootstrapping process.

In the second case you initialize io before bootstrapping app when there is no Angular zone defined.

Related