Hone logo
Hone
Problems

Implementing shareReplay Behavior in Angular Observables

Angular's RxJS library provides powerful tools for reactive programming. The shareReplay operator is a crucial component for optimizing performance and managing shared data streams, particularly when dealing with components that subscribe late to an observable. This challenge asks you to implement the core functionality of shareReplay in TypeScript, mimicking its behavior within an Angular context.

Problem Description

The goal is to create a function shareReplay that takes an Observable and a buffer size (number) as input and returns a new Observable. This new Observable should behave like RxJS's built-in shareReplay operator: it should replay the last buffer size values emitted by the source Observable to any new subscribers. Essentially, new subscribers should receive a "snapshot" of the recent history of the observable.

Key Requirements:

  • Replay Buffer: The function must maintain a buffer of the last buffer size values emitted by the source Observable.
  • Late Subscribers: New subscribers should receive all values in the buffer when they subscribe.
  • Source Observable Completion: When the source Observable completes, the shareReplay Observable should also complete.
  • Error Handling: If the source Observable emits an error, the shareReplay Observable should also emit the error and complete.
  • Unsubscribe: When the shareReplay Observable is unsubscribed from, it should decrement a subscription count. If the subscription count reaches zero, the source Observable should be unsubscribed from.

Expected Behavior:

The shareReplay Observable should act as a multicast subject, sharing the source Observable's emissions with all subscribers. However, unlike a regular Subject, it replays a specified number of previous emissions to new subscribers.

Edge Cases to Consider:

  • Buffer Size of 0: Should behave similarly to share (no replay).
  • Buffer Size Larger than Emissions: Should replay all emissions.
  • Multiple Subscribers: Ensure all subscribers receive the same emissions in the correct order.
  • Source Observable Completes Before Subscribers: The shareReplay Observable should complete immediately.
  • Source Observable Errors Before Subscribers: The shareReplay Observable should error immediately.

Examples

Example 1:

Input: shareReplay(of(1, 2, 3), 2)
Output:  Subscriber 1 receives: 2, 3. Subscriber 2 receives: 2, 3.
Explanation: The source Observable emits 1, 2, and 3.  The buffer size is 2.  Both subscribers receive the last two emissions (2 and 3).

Example 2:

Input: shareReplay(of(1, 2, 3), 5)
Output: Subscriber 1 receives: 1, 2, 3. Subscriber 2 receives: 1, 2, 3.
Explanation: The source Observable emits 1, 2, and 3. The buffer size is 5 (larger than the number of emissions). Both subscribers receive all emissions.

Example 3:

Input: shareReplay(defer(() => of(4, 5, 6)), 2)
Output: Subscriber 1 receives: 4, 5, 6. Subscriber 2 receives: 4, 5, 6.
Explanation: The source Observable emits 4, 5, and 6. The buffer size is 2. Both subscribers receive the last two emissions (5 and 6) and the next emission (6).

Constraints

  • Buffer Size: The buffer size will always be a non-negative integer.
  • Source Observable: The input Observable can emit any type of value.
  • Performance: The solution should be reasonably efficient. Avoid unnecessary memory allocations or complex operations. While absolute performance isn't the primary focus, avoid obviously inefficient approaches.
  • No External RxJS Operators: You are not allowed to use RxJS's built-in shareReplay operator or any other operators that directly implement the same functionality. You must implement the core logic yourself.

Notes

  • Consider using a simple array to store the replay buffer.
  • Think about how to handle the subscription count and unsubscribe from the source Observable correctly.
  • The defer operator from RxJS can be helpful for creating Observables that are only created when subscribed to.
  • Focus on the core replay logic and subscription management. Error handling and completion are also important.
  • This is a good exercise in understanding how RxJS operators work under the hood.
Loading editor...
typescript