Katkat

Debug an Angular UI from User Reports

WaymoFrontend Engineer · Onsite

Last updated

This problem tests your ability to debug an Angular component, specifically focusing on Change Detection strategies, memory leaks in RxJS subscriptions, and asynchronous state management.

The Problem: The Stale Simulation Monitor

You are working on a Simulation Monitor dashboard in Angular. Users report that the component frequently displays "stale" simulation progress data even when new WebSocket messages are received. Additionally, the browser tab memory usage climbs steadily while the monitor is active.

Current Implementation

@Component({
  selector: 'app-sim-monitor',
  template: `
    Status: {{ status }}
    Toggle Updates
  `
})
export class SimMonitorComponent implements OnInit {
  status = 'Disconnected';

  constructor(private simService: SimulationService) {}

  ngOnInit() {
    this.simService.getUpdates().subscribe(data => {
      this.status = data.status;
      console.log('Update received:', data);
    });
  }

  togglePolling() {
    this.simService.toggle();
  }
}

Known Issues

  1. Memory Leak: The getUpdates() observable is never unsubscribed, leading to detached subscriptions if the component is destroyed and recreated.
  2. Change Detection: The UI does not always reflect changes immediately, despite the status variable updating correctly in the logic.
  3. Race Conditions: Rapidly toggling polling triggers multiple concurrent subscriptions.

Your Task

  1. Explain why the UI fails to update and why memory increases.
  2. Provide a refactored version of the ngOnInit and cleanup logic.
  3. Write a conceptual unit test (using Jasmine/Karma style) to verify that the subscription is cleaned up when the component is destroyed.

Hints

Hint 1

Consider the lifecycle hooks available in Angular for handling resource cleanup when a component is destroyed.

Hint 2

Think about using the 'async' pipe in the template instead of manual subscription, or implementing the 'takeUntil' pattern.

Hint 3

The OnPush change detection strategy is often used in performance-sensitive dashboards; consider how it interacts with manual data updates.

Follow-up questions

  • How would you optimize this component if the SimulationService pushed updates 60 times per second?
  • Explain the difference between 'ngOnDestroy' and the 'takeUntil' operator in terms of component robustness.
  • If you were to introduce a 'Loading' state, how would you ensure the UI remains responsive during slow WebSocket reconnection attempts?