Implementing a Custom Async Pipe in Angular
Angular's built-in AsyncPipe is a powerful tool for subscribing to Observables and automatically updating the template when new values are emitted. However, sometimes you need more control or specific behavior than the default AsyncPipe provides. This challenge asks you to implement a custom async pipe that handles error states and provides a default value when the Observable is initially empty.
Problem Description
You need to create a custom Angular pipe named CustomAsyncPipe that wraps an Observable. This pipe should:
- Subscribe to the Observable: The pipe should subscribe to the Observable passed to it.
- Emit Values: The pipe should emit the latest value from the Observable to the template.
- Handle Errors: If the Observable emits an error, the pipe should emit a predefined error message.
- Provide a Default Value: If the Observable is initially empty (doesn't emit a value immediately), the pipe should emit a default value until the Observable emits its first value.
- Unsubscribe: The pipe must unsubscribe from the Observable when the pipe is destroyed to prevent memory leaks.
Key Requirements:
- The pipe should be reusable and accept an Observable and a default value as input.
- The error message should be configurable.
- The pipe should be pure (i.e., it shouldn't perform any side effects other than subscribing to and emitting from the Observable).
Expected Behavior:
- When the pipe receives an Observable, it should immediately emit the default value.
- When the Observable emits a value, the pipe should emit that value, replacing the default value.
- If the Observable emits an error, the pipe should emit the configured error message.
- When the component using the pipe is destroyed, the pipe should unsubscribe from the Observable.
Edge Cases to Consider:
- What happens if the Observable completes? (The pipe should stop emitting values.)
- What happens if the Observable emits multiple values quickly? (The pipe should emit the latest value.)
- What happens if the Observable never emits a value? (The pipe should continue to emit the default value indefinitely.)
- What happens if the input Observable is null or undefined? (Handle gracefully, perhaps by emitting the default value and not subscribing.)
Examples
Example 1:
Input: Observable<number> emitting [1, 2, 3] and default value 0, error message "Error occurred"
Output: 0, 1, 2, 3
Explanation: The pipe initially emits the default value (0). Then, it emits the values from the Observable (1, 2, 3).
Example 2:
Input: Observable<string> emitting "Hello" and default value "Loading...", error message "Failed to load"
Output: "Loading...", "Hello"
Explanation: The pipe initially emits the default value ("Loading..."). Then, it emits the value from the Observable ("Hello").
Example 3:
Input: Observable<number> emitting an error "Network Error" and default value -1, error message "Connection failed"
Output: -1, "Connection failed"
Explanation: The pipe initially emits the default value (-1). Then, it emits the error message "Connection failed".
Constraints
- The pipe must be implemented in TypeScript.
- The pipe must be a pure pipe.
- The pipe must handle errors gracefully.
- The pipe must unsubscribe from the Observable when destroyed.
- The Observable input can be of any type.
- The default value and error message should be strings.
Notes
- Consider using the
takeUntiloperator to unsubscribe when the pipe is destroyed. - Think about how to handle the initial emission of the default value before the Observable emits its first value.
- Remember that pipes are pure functions and should not have any side effects. The subscription and emission are the core functionality.
- You'll need to create a new Angular module to test your pipe. Don't worry about creating a full application. Just focus on the pipe implementation and a simple component to use it.