Hone logo
Hone
Problems

Real-time Data Synchronization with RxJS Observables in Angular

This challenge focuses on building a robust real-time data synchronization mechanism within an Angular application. You will implement a service that utilizes RxJS Observables to manage and broadcast changes to a collection of items, allowing multiple components to react to updates seamlessly. This is a fundamental pattern for creating dynamic and responsive user interfaces.

Problem Description

You need to create an Angular service, DataSyncService, that manages a collection of Item objects. This service should expose an Observable that emits the current state of the entire collection whenever any item is added, updated, or removed. Components can subscribe to this Observable to stay updated with the latest data without manual polling.

Key Requirements:

  1. Item Interface: Define an Item interface with at least an id (number, unique) and a name (string) property.
  2. DataSyncService:
    • Maintain an internal array of Item objects.
    • Provide methods to:
      • addItem(item: Item): Adds a new item to the collection.
      • updateItem(item: Item): Updates an existing item in the collection by its id.
      • removeItem(id: number): Removes an item from the collection by its id.
      • getItems(): Observable<Item[]>: Returns an Observable that emits the current state of the entire Item collection.
    • Ensure that each modification operation (add, update, remove) triggers a new emission from the getItems() Observable.
  3. Component Interaction: Demonstrate how a component can subscribe to the getItems() Observable and display the data. It should also be able to trigger modifications through the DataSyncService.

Expected Behavior:

  • When addItem is called, the Observable emitted by getItems() should include the new item.
  • When updateItem is called with a matching id, the corresponding item in the collection should be updated, and the Observable should emit the modified collection.
  • When removeItem is called with a matching id, the item should be removed, and the Observable should emit the updated collection.
  • Multiple components subscribing to getItems() should all receive the same updates simultaneously.

Edge Cases:

  • Attempting to update or remove an item that does not exist (based on id). These operations should ideally be silent or provide feedback if necessary (though for this challenge, simply not performing the action is acceptable).
  • Adding an item with an id that already exists. For simplicity, assume unique IDs are provided or handle this case by rejecting duplicate IDs.

Examples

Example 1: Basic Add and Subscribe

// In DataSyncService
const service = new DataSyncService();
service.getItems().subscribe(items => console.log('Current items:', items)); // Initial emission will likely be empty

const newItem = { id: 1, name: 'Apple' };
service.addItem(newItem);
// Expected console output after addItem: Current items: [ { id: 1, name: 'Apple' } ]

const anotherItem = { id: 2, name: 'Banana' };
service.addItem(anotherItem);
// Expected console output after addItem: Current items: [ { id: 1, name: 'Apple' }, { id: 2, name: 'Banana' } ]

Example 2: Update and Remove

// Assuming DataSyncService is already populated as in Example 1

// Update
const updatedItem = { id: 1, name: 'Red Apple' };
service.updateItem(updatedItem);
// Expected console output after updateItem: Current items: [ { id: 1, name: 'Red Apple' }, { id: 2, name: 'Banana' } ]

// Remove
service.removeItem(2);
// Expected console output after removeItem: Current items: [ { id: 1, name: 'Red Apple' } ]

Example 3: Handling Non-existent IDs

// Assuming DataSyncService is populated with { id: 1, name: 'Grape' }

// Attempt to update non-existent item
const nonExistentUpdate = { id: 99, name: 'Watermelon' };
service.updateItem(nonExistentUpdate);
// Expected console output: No change. The Observable should emit the current state: [ { id: 1, name: 'Grape' } ]

// Attempt to remove non-existent item
service.removeItem(100);
// Expected console output: No change. The Observable should emit the current state: [ { id: 1, name: 'Grape' } ]

Constraints

  • The id property of an Item must be unique within the collection.
  • All operations (add, update, remove) must be synchronous within the service.
  • The getItems() Observable must be a "hot" Observable (meaning multiple subscribers share the same underlying execution). BehaviorSubject is a good candidate.
  • The solution should be implemented in TypeScript.

Notes

  • Consider using BehaviorSubject from RxJS. It's ideal for managing a current value and emitting it to new subscribers.
  • Think about how to efficiently find and modify items within the internal array.
  • You'll need to create a simple Angular component to demonstrate the subscription and interaction with the service. The focus is on the service and observable pattern, so the component UI can be very basic.
  • The getItems() observable should always emit a new array instance when changes occur, even if the contents are the same (e.g., if an update operation results in no visible change to the array structure but the item's properties are modified). This helps RxJS's change detection mechanisms.
Loading editor...
typescript