Is emitting a side effect event acceptable within an RxJS pipe?

Currently, I am utilizing RxJS within the context of an Angular application.

Within my service, there is functionality to reinitialize the entire application with different settings as needed.


@Injectable()
class BootstrapService{

 public initApplication(config: appConfig): Observable<boolean>{
        return someObservable;
 };
}

The intended use case scenario would be:


///.... code in part of application that allows user to reinit app

this.bootstrapService.initApplication({someconfig}).subscribe(result=>{
  if(result){
      //report success
   }else report failure
}
}

This functions similarly to a cold observable, resembling http calls.

Now, I have a requirement to send additional notifications to specific components (such as updating user menus, toolbars, etc. with new configuration from the server).

I plan to achieve this by emitting an event at the end of the pipe inside BoostrapService#initApplicaiton, like so:

 
public initApplication(config: appConfig): Observable<boolean>{
       return someObservable().pipe(tap(result=>if(result)this.subject.next(someEvent))
 };

This can be seen as a side effect, which is typically discouraged in functional programming, based on information available online.

So the question arises - is it acceptable to emit events as side effects, or should a different approach be taken?

Another potential solution that comes to mind involves creating a "hot" observable that isn't returned to the caller, but rather a shared stream is used instead:


appInitResult: Subject<boolean>
 public initApplication(config: appConfig): Observable<boolean>{
      someObservable().subscribe(r-> this.appInitResult.next(r));
  return this.appInitResult.asObservable();
 };

This way, everything can subscribe to the same stream, including the method caller.

Answer №1

Although it's best to avoid external side effects, there are times when they cannot be completely eliminated. It seems like the way you're handling this side effect is appropriate.

With that said, I'm curious about the specific scenario that necessitates reinitializing the app.

For example, in a situation where a user is logged in, you can establish a reactive data flow within your app. By placing the user observable at the forefront of this flow, any changes to the user object will trigger corresponding updates in all observables throughout the app.

While setting this up may seem complex, utilizing observables extensively is key to achieving seamless functionality.

Answer №2

It seems like you are utilizing Angular, so allow me to share my perspective on the situation.

If I understand correctly, your application involves multiple components that are interested in the same stream of events.

In such a scenario, I would recommend creating a myService with 2 APIs:

  • a public Observable that notifies the components about the event they are interested in
  • a public method that enables an external client of the myService to trigger the event notification

To implement this, the code would look something like this:

@Injectable()
class MyService{
 private _myEvent = new Subject<any>()
 public myEvent = this._myEvent.asObservable()

 public notifyEvent(event: any) {
   this._myEvent.next(event)
 };
}

Any component or service that wishes to utilize myService can access it through Dependency Injection and employ its functionalities.

For instance, a BootstrapService would be structured as follows:

@Injectable() class BootstrapService{ constructor(private myService: MyService) {}

public initApplication(config: appConfig) { // perform necessary actions to generate the event const _event = buildEvent(config) this.myService.notifyEvent(event) }; }

Another component requiring notifications can be designed similarly:

@Injectable()
class MyComponent{
 constructor(private myService: MyService) {}
 
 // use myService.myEvent as needed, such as subscribing to it in ngOnInit
 public ngOnInit() { 
        const _event = buildEvent(config)
        this.myService.myEvent.subscribe({
          next: event => {
             // perform actions using the event data
          }
        })
 };
}

Components structured in this manner can also directly utilize myService.myEvent within the template with the async pipe, especially if the objective is solely to display information present in the event.

You might find this article informative. While it discusses React, the concept of the service aligns with what was described above.

Lastly, in reference to your statement about "functional programming should avoid side effects," it should be interpreted cautiously.

Functional programming cannot completely eliminate side effects. A program requires side effects to perform useful actions like writing or displaying information. The key is to isolate these side effects, which is where functional programming can assist by isolating side effects.

In this case, the side effects are isolated within the subscribe logic.

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

Obtain data from a single module and incorporate it into a different one

In my Angular 2 application, I am dealing with two component files - home.ts and folder-selector.ts. Within the folder-selector.ts file, there is a variable named pathToNode. I am trying to figure out how to access this value from within the home.ts file ...

The issue of Angular 2.3.1 custom validator promise not resolving

I am currently working on implementing a sign up form in which I need to check if the username is already taken or not. To accomplish this, I have decided to use promises. The structure of my sign-up component is as follows: import { Component, OnInit } f ...

Adding a value to an array in TypeScript

When trying to add values to an array in my code, I encountered an error stating that "number" is not a valid type for the array. someArray: Array <{ m: number, d: Date}> = []; this.someArray.push(500,new Date(2020,1,15)); ...

The key is not applicable for indexing the type as expected

Here is the TS code I am working with: type Fruit = { kind: "apple" } | { kind: "grape"; color: "green" | "black" }; type FruitTaste<TFruit extends Fruit> = TFruit["kind"] extends "apple" ? "good" : TFruit["color"] extends "green" ? "good" : ...

Switch the Follow/Following button depending on the user's current follow status with the individual

I am currently working on a functionality to toggle between the Follow and Following buttons based on whether the current user is following another individual. I have implemented an NgIF statement in my code, but I am facing challenges in properly checking ...

Processing dates with NestJS

I am trying to format a date string in my NestJS API from 'YYYY-mm-dd' to 'dd-mm-YYYY', or even better, into a date object. Unfortunately, the NestJS framework does not seem to recognize when Angular sends a Date as well. Should I be se ...

The server encountered an issue with starting the ANCM Out-Of-Process, resulting in HTTP Error 502

We currently have two projects in progress. One involves a Web API built on .NET Core 2.2.6 and an Angular 8 Single Page Application integrated within .NET Core 2.2.6. Both projects have been deployed on IIS 7 with the Web API functioning properly, but the ...

Having trouble retrieving object property despite returning an object type - React with Typescript

I am facing a issue with my React state where I have an array of objects and I am adding an object to it using the setState method. The objects are successfully added to the array. However, when I try to access the properties of the object in another func ...

Display the value of a shortened string

My Goal I aim to develop a method for determining the amount of a string visible before it gets cut off. Motivation In my project, there is a collection of items that can be chosen. A panel presents a concatenated string of the selected item names separa ...

Managing time in an Angular application using Typescript

I am facing an issue with formatting the time obtained from an API in my FormArray. The time is received in the format: 14.21.00 My goal is to convert this time to the following format: 2:21 PM I have attempted to format it using Angular's DatePip ...

What is the best way to integrate Tawk.to into a React application while using typescript?

Having some issues integrating tawk.to into my website built with React and TypeScript. I have installed their official npm package, but encountered an error message: import TawkMessengerReact from '@tawk.to/tawk-messenger-react'; Could not fin ...

Using a configuration file with the JavaScriptServices React-Redux template

I have come across this question many times on different platforms, but I haven't been able to make it work for me. The issue is that I am using an API within a React component (with TypeScript 2.4.1 and webpack 2.5.1): .... fetch("some/url/api/", me ...

The module '@angular/material' could not be located, please check for errors

An Issue Arises The module '@angular/material' cannot be located. In the file app.module.ts import { MaterialModule } from '@angular/material'; Find more information here: https://material.angular.io/guide/getting-started npm in ...

Preventing automatic download and storage of images and videos in an Ionic application

Currently, my chat application allows users to send and receive media such as photos and videos. However, when I open the message page, it automatically downloads and backs up all the media. I am looking to change this functionality on my Ionic page so th ...

Using interpolation brackets in Angular2 for variables instead of dots

I'm curious if Angular2 has a feature similar to the bracket notation in Javascript that allows you to use variables to select an object property, or if there is another method to achieve the same functionality. Here is the code snippet for reference ...

Troubleshooting Problem with Dependency Injection in Angular 2 Services

Within my application, there is a Module that consists of two components: ListComponent and DetailsComponent, as well as a service called MyModuleService. Whenever a user visits the ListComponent, I retrieve the list from the server and store it in the Li ...

Issues arise during the deployment of Angular7 production build when passing through the Bitbucket package manager

I am working on a project to create a system that allows Angular components to be reused across multiple applications via BitBucket. Currently, I have the following setup: BitBucket Repo A - This repository stores the node module. The module is develope ...

Is it necessary to separate Lodash orderby functions to ensure they function correctly?

For some reason, I'm having trouble sorting my data using lodash in my front-end client code. All the examples I've come across don't involve working with data in an interface, so I can't figure out where I'm going wrong. Let&apo ...

How to convert the return value of a function into a string in Angular 2

I am hoping to place the returned value within this markup: <h2>{{getSelectedUserName}}</h2> Below is the function I intend to utilize, which will return a string: public getSelectedUserName(): string { let firstName = this.selectedUser. ...

Is Angular9 BehaviorSubject from rxjs giving trouble across different components?

I am facing an issue with updating data in real-time from the profile component to the header component. Initially, it works fine but after updating any value in the profile component, the header observable does not subscribe again. To solve this problem, ...