Observable - initiating conditional emission

How can I make sure that values are emitted conditionally from an observable? Specifically, in my scenario, subscribers of the .asObservable() function should only receive a value after the CurrentUser has been initialized.

export class CurrentUser {

    private currentUser$: Observable<CurrentUser>;
    private currentUserBehaviorSubject: BehaviorSubject<CurrentUser>;

    public name: string = "";

    constructor() {
        this.currentUserBehaviorSubject = new BehaviorSubject(this);
        this.currentUser$ = this.currentUserBehaviorSubject.asObservable();
    }

    public asObservable(): Observable<CurrentUser> {
        // 
        if(user.name.length > 0){
            return this.currentUser$;
        }
        else {
            // ?????
        }
    }

    public initialize(string name){
        this.name = name;
        this.currentUserBehaviorSubject.next(this);
    }
}

export class SampleComponent {
    constructor(
        currentUser: CurrentUser
    ) {
        currentUser.asObservable().subscribe(
            (u: CurrentUser) => {
                // i only want an INITIALIZED user here
            },
            error => {},
            () => { }
        );
    }
}

Answer №1

One possible approach is to modify your asObservable() method so it always returns an Observable and utilizes the skipUntil() operator to suppress emissions until currentUserBehaviorSubject emits (indicating that CurrentUser has been initialized):

public asObservable(): Observable<CurrentUser> {
    return this.currentUser$
        .skipUntil(this.currentUserBehaviorSubject);
}

Answer №2

Here's my perspective:

export class CurrentUser {
    subject: Subject<CurrentUser> = new Subject<CurrentUser>();
    observable: Observable<CurrentUser = this.subject.asObservable();

    constructor() {
        // Handle your tasks here
        this.subject.next(this);
    }
}

In your components, simply subscribe to the observable property.

By following this approach, whenever a new CurrentUser is initialized, all observers will be notified. Does this align with your intentions, or am I missing something?

Answer №3

My typical approach for managing such cases is as follows:

  private dataSubject = new BehaviorSubject<any>(null);
  private initSubject$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);

getData(): Observable<any> {
  return this.dataSubject.pipe(
    skipUntil(this.initSubject$.pipe(filter(isInitialized => isInitialized === true)))
  )
}

setData(data) {
  this.initSubject$.next(true);
  this.dataSubject.next(data);

}

By following this pattern, the handling of initialized and uninitialized data solely depends on updating the source observable, which is connected to an initialization observable. This can be optimized further by using a static observable for initialization, but the outcome remains the same:

No need for conditional statements in data emission logic; subscribers waiting for data before initialization will simply queue up until the initial data arrives.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Generics causing mismatch in data types

I decided to create a Discord bot using DiscordJS and TypeScript. To simplify the process of adding components to Discord messages, I developed an abstract class called componentprototype. Here is how it looks (Please note that Generators are subclasses li ...

Saving a user with a BLOB avatar in Angular 5: Tips and Tricks for Success

As a newcomer to Angular, I am trying to figure out how to properly save a new user with an avatar. Can someone help me understand how to pass the Blob value of the avatar to my user Model for successful saving? Below is the code snippet I am working with ...

Determine the return value of a function based on a specific conditional parameter

Is it possible for a function with a parameter of a conditional type to return conditionally based on that parameter? Explore the concept further here I am faced with a scenario where I have a function that takes one parameter, which can either be a cust ...

Binding textarea data in Angular is a powerful feature that allows

I am looking to display the content from a textarea on the page in real time, but I am struggling to get the line breaks to show up. Here is my current code snippet: app.component.html <div class="ui center aligned grid">{{Form.value.address}}< ...

Encountering Issue: Unable to locate control with the given name in Angular when generating Dynamic Form with FormGroup

As a beginner in Angular, I aim to develop a dynamic Survey Form that can adjust its questions and input types based on the area. These changes are fetched as JSON data through API calls. Here is the relevant code snippet: .ts File export class Maintenan ...

Angular 2 - Utilizing a Shared Service for Subscriptions

After referencing this guide: Parent and children communicate via a service I have decided to utilize a shared service instead of EventEmitter. The reason being that EventEmitter only facilitates communication between parent and child components, which do ...

Images are failing to load in Ionic 3

Currently working on developing an Ionic application and troubleshooting the use of the camera native plugin. The script functions flawlessly in a fresh project, but encounters issues within the current project environment. Initially suspected a problem w ...

The type undefined cannot be assigned to the type even with a null check

When looking at my code, I encounter an error stating Argument of type 'Definition | undefined' is not assignable to parameter of type 'Definition'. Even though I am checking if the object value is not undefined with if (defs[type] != u ...

Test Transmission Service

Hey there, I'm currently working on writing Angular code for a component that involves an observable. However, I'm facing some issues testing the broadcast service as I keep getting an error indicating that the service is not being called. Does a ...

A step-by-step guide on leveraging swagger-autogen in TypeScript applications

Is it possible to integrate the swagger-autogen module into a Typescript project? I have attempted multiple methods, but have been unsuccessful. The error message "Failed" keeps appearing when using a swagger.js file: const swaggerAutogen = require("swagge ...

Determine an expression based on a string in Typescript

Looking at the code snippet below, everything appears to be in order (view playground): type PathParam<T> = T extends `${string}:${infer U}` ? U : never; type Param = PathParam<"/post/:post_id">; // type Param = "post_id" ...

Issue with the drag functionality of Framer Motion carousel causing malfunction

Attempting to create a basic Image Carousel using framer-motion for added functionality. The goal is to incorporate both buttons and drag control for sliding through the images. Currently, it functions properly, but if the slider overshoots on the last im ...

Tips for utilizing RouterLink within an HTML template

Angular 2.3.0 I created a module in Angular 2 as shown below: import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { RouterModule, Routes } from '@angular/router'; impo ...

Issue with TypeScript Decorator Not Properly Overriding Get/Set Functions for Instance Properties

I'm struggling with creating a TypeScript decorator that modifies the get method for a property within a class. The issue I'm facing is getting it to affect instances of the class. Below is an example scenario: function CustomDecorator() { r ...

Saving files to MinIO from an Angular2 web form

I am currently working on a prototype for an Angular8 application that is capable of uploading files from a form to MinIO. Below is the structure of the form: upload-form.component.html : <input class="form-control" type="file" (change)="onFileCha ...

The pipe in Angular 2.0.0 was not able to be located

Error: Issue: Template parse errors: The 'datefromiso' pipe is not recognized Custom Pipe: import {Pipe, PipeTransform} from "@angular/core"; @Pipe({ name: 'datefromiso' }) export class DateFromISO implements P ...

Angular 2 - Utilizing `return` in the `then` method for async operations

Currently, I am facing a scenario where it would be very useful if there was a way to retrieve the value obtained in the .then() function. Allow me to explain why and what exactly I need. For almost every API call, I need to include the API_KEY and DEVIC ...

Map does not provide zero padding for strings, whereas forEach does

Currently working on developing crypto tools, I encountered an issue while attempting to utilize the map function to reduce characters into a string. Strangely enough, one function works perfectly fine, while the other fails to 0 pad the string. What could ...

Ionic 2 Media Plugin File Status with Ionic Native

In the Ionic Native Media plugin documentation found here, it mentions that there are both static and instance members, such as status. I am looking for an example related to the file status in the media plugin. I attempted to do this: console.log(this. ...

Issue with Material UI v5: "spacing" property not found on custom theme object

My current setup involves using version 5 of material ui, where I have customized a theme and applied it to all my components. However, when trying to add padding to a paper element in one of my components based on the theme, I encountered the following e ...