When accessing APIs, create an array of observables for each user call and then trigger a function once all are successfully resolved

As I aim to generate a list of observables while a user engages with the webpage, I am faced with the challenge of individually subscribing to each observable, but desiring another function to execute after individual or multiple simultaneous API calls are completed.

I have successfully implemented each function to add an observable to an array, and have utilized forkJoin and subscription to the array in my ngOnInit. However, this setup only executes once. How can I establish a real-time subscription that triggers a callback function after all ongoing API calls finish, and continues to do so as the user makes further API calls?

For instance, if the user clicks "Create Thing," then remains idle.

forkJoin(thingsInProgress).subscribe(() => doStuffWhenAllResolve())

...

createThing() {
    const createThing$ = this.thingService.createThing().pipe(tap(() => doStuff()));
    thingsInProgress.push(createThing$);
    createThing$.subscribe();
}

deleteThing() {
    ...
}

updateThing() {
    ...
}

I anticipate doStuff() to execute first, followed by doStuffWhenAllResolve(). Alternatively, in a scenario where the user rapidly clicks "Create Thing," "Delete Thing," "Update Thing" almost simultaneously, doStuff() (as an example) should be invoked individually for each action, while doStuffWhenAllResolve() should be invoked collectively for all actions.

Furthermore, if the user swiftly creates an additional 10 things, doStuffWhenAllResolve() should be triggered once more upon completion of all concurrent API calls.

Which RXJS operator should I be searching for in this situation?

Answer №1

To ensure smooth operation, I recommend implementing a BehaviorSubject that triggers events for createThing(), deleteThing(), and updateThing(), all accompanied by a debounceTime for optimal performance.

Here is a sample implementation:

actionMade$ = new BehaviourSubject(new Date());

this.actionMade$.pipe(
  debounceTime(100), 
  switchMap(() => forkJoin(thingsInProgress)),
).subscribe(() => doStuffWhenAllResolve());

createThing() {
  ...
  this.actionMade$.next(new Date());
}

deleteThing() {
  ...
  this.actionMade$.next(new Date());
}

updateThing() {
  ...
  this.actionMade$.next(new Date());
}

ngOnDestroy() {
  this.actionMade$.complete();
}

==================================================== Remember to unsubscribe from subscriptions using sub.unsubscribe or takeUntil to prevent memory leaks.

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

How can Angular 2 effectively keep track of changes in HTTP service subscriptions? Calling the method directly may result in

After making a call to the authentication service method that checks the validity of the username and password, as well as providing an authentication token, I encountered an issue. When attempting to display the value obtained from calling the getAuthData ...

Encountering a "property does not exist" error while using VS Code TypeScript within a Vue.js project

I am working on a Vuejs project in Typescript. The project compiles and runs perfectly without any errors. However, I am facing an issue with the TS linter. In my individual component files, I am using the component decorator as shown below: //videocard.c ...

Investigating TypeScript Bugs in Visual Studio Code

As I navigate through various sources, I notice that there is a plethora of information available on older versions of VSCode (v1.16.1 - the most recent version at the time of writing) or deprecated attributes in the launch.json file. I have experimented ...

Encountering a TypeScript issue when integrating @material-tailwind/react with Next.js 14

Attempting to incorporate "@material-tailwind/react": "^2.1.9" with "next": "14.1.4" "use client"; import { Button } from "@material-tailwind/react"; export default function Home() { return <Button>Test MUI</Button>; } However, the button i ...

What is the best way to detect component errors on the server with Angular Universal?

Here is a snippet of my server code that renders the Angular home.component: app.get("*", (req, res) => { res.render( `../${CLIENT_DIST_DIR}/index`, { req: req, res: res, providers: [ ...

Tips for running Typescript files on a server in the background

I am currently working on a NodeJS application that consists solely of TypeScript files, without any JavaScript files. I'd like to run it on my server in the background. Any suggestions on how I can achieve this? I experimented with using the npm pa ...

The data type of the element is implicitly set to 'any' due to the fact that a 'string' expression cannot be used to reference the type '(controlName: string) => boolean'

checkError(typeofValidator: string, controlName: string): boolean { return this.CustomerModel.formCustomerGroup.contains[controlName].hasError(typeofValidator); } I am currently learning Angular. I came across the same code in a course video, but it i ...

The MdIcon in Angular 2 Material that functions properly in one component is causing issues in another

After upgrading from ng2 rc4 with material2 alpha6 to ng2 rc5 with material 2 alpha7-2, I encountered a new error related to the usage of <md-icon> which was previously working fine. The error message that appears now is Observable_1.Observable.thro ...

What is the best way to utilize a reduce function to eliminate the need for looping through an object in JavaScript?

Currently, my code looks like this: const weekdays = eachDay.map((day) => format(day, 'EEE')); let ret = { Su: '', Mo: '', Tu: '', We: '', Th: '', Fr: '', Sa: '' }; w ...

Error: TypeScript cannot locate the specified <element> in the VSCode template

After conducting some observations, I've come to realize that the error is specific to the first .tsx file opened in VSCode. Once IntelliSense runs on this initial file, the error appears. Subsequent files work fine without any issues. To troubleshoo ...

Components for managing Create, Read, Update, and Delete operations

As I embark on my Angular 2 journey with TypeScript, I am exploring the most efficient way to structure my application. Consider a scenario where I need to perform CRUD operations on a product. Should I create a separate component for each operation, such ...

There appears to be a TypeScript error in the cheerio-select library located at /home/Documents/node_modules/cheerio-select/lib/index.d.ts(1,15): missing comma. Error code: TS1005

Hello, I encountered an error in my terminal while trying to run npm run dev & npm run build. [0] The compilation failed. [0] [0] /home/Documents/frontend/node_modules/cheerio-select/lib/index.d.ts [0] TypeScript error in /home/fislam/Documents/fronten ...

What is the reason behind TypeScript requiring me to initialize a property even though I am retrieving its value from a local reference?

I am just beginning to explore Angular. This is the template for my custom component: <div class="row"> <div class="col-xs-12"> <form action=""> <div class="ro"> <d ...

Angular encountered an error while attempting to manage a base service that was not defined

My service involves extending a base service to handle error data effectively. For instance import { CurrentUserService } from './current-user.service'; import { CONFIG } from './../shared/base-urls'; import { BaseServiceService } fro ...

Creating a backup link for a video player component in NextJs

My aim is to make sure that two video player components in a NextJS application can still access and play videos even when the application is running locally using npm run dev without an internet connection. Currently, these two components.. <HoverVi ...

Disabling exit view mode in the Unlayer email editor: A guide

Currently, I am able to open a preview using the code unlayer.showPreview("desktop"). However, whenever the user clicks on the overlay, they are exiting the preview mode. Is there a way to prevent the user from closing the preview? Unfortunatel ...

Typeorm stored procedure that returns a JSON response

Whenever I execute the stored procedure defined in a Microsoft SQL database using TypeORM as shown below: const result=await conn.query('exec Spname @0,@1',[inp1val,inp2val]); I receive a response from the database, but it comes with an addition ...

Error in Angular: Unable to Access Property '..' of null

Having an issue with my Angular project where I keep getting an error message saying "cannot read property of '...' of undefined" whenever I select an employee from the combo box. The '...' represents the index of the selected employee. ...

Can you explain the distinction between interfaces containing function properties written as "f()" and "f: () =>"?

Let's take a look at two interfaces, A and B: interface A {f(): number} interface B {f: () => number} I have experimented with the following: var a: A = {f: function() {return 1}} var a: A = {f: () => 1} var b: B = {f: function() {return 1}} ...

Property of object (TS) cannot be accessed

My question relates to a piece of TypeScript code Here is the code snippet: export function load_form_actions() { $('#step_2_form').on('ajax:before', function(data) { $('#step_2_submit_btn').hide(); $(&ap ...