Hone logo
Hone
Problems

Implementing Angular's TransferState for Seamless Navigation

Angular's TransferState is a powerful mechanism for preserving application state during navigation, particularly useful for Single Page Applications (SPAs) where full page reloads are undesirable. This challenge asks you to implement a basic TransferState service that allows you to store and retrieve state data between different routes, ensuring a smoother user experience by minimizing data loss during transitions.

Problem Description

You need to create an Angular service called TransferState that manages application state. This service should provide methods for:

  1. Storing State: A method to store a key-value pair of data. The key should be a string, and the value can be any data type.
  2. Retrieving State: A method to retrieve data associated with a given key. If the key doesn't exist, it should return undefined.
  3. Clearing State: A method to remove a specific key-value pair from the state.
  4. Resetting State: A method to clear all stored state.

The TransferState should be designed to be used with Angular's router. While you don't need to integrate it directly with the router in this challenge, consider how it would be used in a real-world scenario (e.g., storing search query parameters, form data, or UI state).

Key Requirements:

  • The service must be injectable into Angular components.
  • The state should be stored in memory. (Persistence to local storage or a backend is not required for this challenge).
  • The service should be thread-safe (consider potential race conditions if multiple components access the state concurrently).
  • The service should handle cases where a key is accessed that doesn't exist.

Expected Behavior:

  • Storing a key-value pair should add it to the internal state.
  • Retrieving a key should return the associated value, or undefined if the key is not found.
  • Clearing a key should remove it from the internal state.
  • Resetting the state should remove all key-value pairs.

Edge Cases to Consider:

  • What happens if you try to store a value with an empty key? (Consider throwing an error or silently ignoring it).
  • What happens if you try to retrieve a key that doesn't exist?
  • How does the service handle concurrent access from multiple components?

Examples

Example 1:

Input:
transferState.store('searchQuery', 'angular tutorial');
transferState.store('theme', 'dark');

transferState.retrieve('searchQuery');
transferState.retrieve('theme');
transferState.retrieve('nonExistentKey');

Output:
'angular tutorial'
'dark'
undefined
Explanation: The service correctly stores and retrieves the specified key-value pairs. It also handles the case where a key doesn't exist.

Example 2:

Input:
transferState.store('user', { id: 123, name: 'John Doe' });
transferState.retrieve('user');
transferState.clear('user');
transferState.retrieve('user');

Output:
{ id: 123, name: 'John Doe' }
{ id: 123, name: 'John Doe' }
undefined
Explanation: The service correctly stores and retrieves an object.  The `clear` method removes the key-value pair.

Example 3: (Edge Case)

Input:
transferState.store('', 'someValue'); // Attempt to store with an empty key
transferState.retrieve('someValue');

Output:
(Assuming error handling: throws an error)
undefined (if empty key is silently ignored)
Explanation: Demonstrates handling of an empty key.  The desired behavior (error or ignore) should be documented.

Constraints

  • Data Size: The total size of the stored state should be reasonably limited (e.g., no more than 1MB). While you don't need to enforce this strictly, be mindful of potential memory usage.
  • Key Type: Keys must be strings.
  • Value Type: Values can be any valid JavaScript data type.
  • Performance: Retrieving and storing state should be reasonably fast (O(1) lookup is ideal).

Notes

  • Consider using a Map or Object to store the state internally. Map offers better performance for frequent insertions and deletions.
  • Think about how to handle potential race conditions if multiple components are accessing and modifying the state simultaneously. Using RxJS subjects or other synchronization mechanisms could be helpful, but are not required for this basic implementation.
  • Document your assumptions and design choices clearly. For example, how you handle empty keys.
  • Focus on the core functionality of storing, retrieving, clearing, and resetting state. Integration with the Angular router is not required for this challenge.
Loading editor...
typescript