Using rxjs in combination with SignalR to patiently await asynchronous notifications from background tasks

Currently, I am in the process of properly rewriting a piece of code using rxjs operators. The objective of this code is to make an http call to a webapi controller, which returns a Guid as the id of a long running background operation to be executed on the server. Once the operation is complete, the server will notify the client via SignalR that it has finished, and the client-side code will resume execution (until then, it will remain in a "waiting for response" state).

The original snippet looks like this:

this._service
    .myHttpCall(parameter1)
    .subscribe(
        operationId => {
            let sub = this._notifierHub.onOperationSuccess
                .subscribe(data => {
                    if (operationId !== data.operationId)
                        return;
                    this.notifySuccess();
                    sub.unsubscribe();
                    sub2.unsubscribe();
                });
            let sub2 = this._notifierHub.onOperationFailure
                .subscribe(data => {
                    if (operationId !== data.operationId)
                        return;
                    this.notifyFailure();
                    sub2.unsubscribe();
                    sub.unsubscribe();
                });
        }
    );

This _notifier service in Angular exposes a Subject as an Observable, emitting whenever the SignalR HubConnection emits.

I aim to incorporate the management of the operation Id into the myHttpCall method so that, from the perspective of the calling component, the http call will only be considered complete once the actual operation is marked as complete through SignalR.

What I would like to write is something along these lines:

myHttpCall(parameter1: any) {
    const url = `${this.action("MyHttpCall")}`;
    const body = { parameter1: parameter1 };
    this._http
        .post(url, body, { responseType: "text" })
        .switchMap(operationId => {
            const successObservable = this._notifier
                .onOperationSuccess
                .filter(data => data.operationId === operationId);
            const failureObservable = this._notifier
                .onOperationFailure
                .filter(data => data.operationId === operationId);
            return <what?!>
}

What should be included in the method body so that, as the caller, I can use this structure:

this._service
    .myHttpCall(parameter1)
    .subscribe(
        () => this.notifySuccess(),
        () => this.notifyFailure(),
        () => console.log("HttpCall completed")
    );

?

Answer №1

Have you considered incorporating the race operator within your switchMap function?

This will make use of the observable that emits first.

...switchMap(operationId => {
            const successObservable = this._notifier
                .onOperationSuccess
                .filter(data => data.operationId === operationId);
            const failureObservable = this._notifier
                .onOperationFailure
                .filter(data => data.operationId === operationId);

            return race(successObservable, failureObservable);
}

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

Autocomplete with Angular Material - Handling mat-error

Currently, I am utilizing Angular 6 in conjunction with Angular Material 6.4.2, and I am encountering difficulties displaying errors properly on an autocomplete feature. To better illustrate the issue, I have prepared a StackBlitz demo showcasing the prob ...

Encountering issue with Angular HTTP POST resulting in error 415 when calling .NET Core

Hello, I'm in need of assistance with posting to a .NET Core Web API as I am still new to Angular. I'm attempting to make a POST request at https://localhost:44394/api/SyUsers, but I keep receiving a 415 error. I have tried setting the headers a ...

Managing the "SafeValue must use [property]=binding:" error in Angular when using the (click) event

I am working on creating a Facebook share button, Component, ngOnInit() { this.WebURL = this.domSanitizer.bypassSecurityTrustResourceUrl(this.data.url); this.facebookURL = this.domSanitizer.bypassSecurityTrustResourceUrl("https://www.fa ...

Make sure a Typescript array contains a particular value

Currently, I am in the process of developing a dropdown-style component where the value and options are separate props. My goal is to incorporate Typescript to ensure that the value remains a valid option. Although I could perform this validation at runtim ...

What is the best way to implement pipes and incorporate reusable action buttons in a Mat-table component for maximum reusability?

I am seeking assistance in creating a reusable component for the Angular Material Mat-table. I have made progress on loading data from the parent component to the child component, as can be seen in StackBlitz, but I now want to apply pipes to the data bef ...

Updating the position of an element in HTML is not possible

For my webpage, I am attempting to adjust the position of all images that are displayed. Despite trying to change the position of a single image using the DOM method, I have run into a problem where the position does not update as expected. Although the co ...

What methods can be used to disable Angular's change detection feature?

I am attempting to create a function that can handle both synchronous and asynchronous tasks without triggering change detection upon completion. This function is being triggered by a button click in the user interface. Template file: <button (click)=& ...

Using React to map and filter nested arrays while also removing duplicates

Hello, I recently started working with react and I've encountered a challenge while trying to map an array. const fullMen = LocationMenuStore.menuItems['menu']['headings'].map((headings: any) => { <Typography>{ ...

Can you give me some insights about what an Action Creator is?

function createRefDoneAction(widgetsArray: widget[]): WidgetAction { return { type: actionTypes.REFRESH_WIDGET_DONE, widgets: widgetsArray }; } Could you please clarify the necessity of having two sets of parameters (e.g. 'wid ...

Tips for importing several makeStyles in tss-react

When upgrading from MUI4 to MUI5 using tss-react, we encountered a problem with multiple styles imports in some files. const { classes } = GridStyles(); const { classes } = IntakeTableStyles(); const { classes } = CommonThemeStyles(); This resulted in ...

WCF: Endpoint reference not found

Currently, I am in the process of developing a SharePoint 2013 webpart that requires a label to interact with a SQL Server data table through WCF. I have already set up the WCF interface and main class, and have incorporated the service in my Visual webpar ...

The number of columns in SqlDataReader does not match the expected count

Currently, I am in the process of designing a website using ASP.NET (webforms) and C#. The table I am working with contains a total of 23 columns. Within the code snippet provided below, the variable reader is a SqlDataReader and 'command' is a ...

Retrieve the essential information needed from the REST API

I have a test wordpress blog set up. To enhance the functionality, I developed an angular app that utilizes the wordpress rest api. The app makes a call to an endpoint to retrieve categories. However, the JSON response contains unnecessary data for my appl ...

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" : ...

Minimize the reliance on Jquery within Angular 2 applications

In my Angular 2 component, I utilize TypeScript for writing modules. The code snippet below displays my use of Jquery to access the DOM at a certain level. Is this practice recommended in Angular 2? Could someone please explain the pros and cons of integra ...

An issue arises when using enums in TypeScript

Let's analyze this demonstration. Initially, an enum is created as follows: enum myEnum { a = 'a', b = 'b' } The next step involves creating a similar enum but with the addition of one more numeric value! This alteration is c ...

Creating an observable in rxjs6 Angular6 that automatically unsubscribes itself

I'm attempting to create an observable that will update the database status to 'away' when the mouse hovers over the document. Then, if the mouse becomes active again, it should update the status back to 'online'. Here is my curre ...

Nest JS Guards - Employ either of two approaches

I have implemented two different JWT based strategies in my application: The first strategy involves single sign-on for organization members, where an external provider generates a JWT. The second strategy is for email/password authenticated external user ...

Tips on maintaining continuous ng serve to keep Angular 2 application running indefinitely

I am running an Angular 2 application using the command ng serve --host ip address. Once executed, it starts at the default port and displays the following logs: Hash: ddb0ab205ea65648a918 Version: webpack 2.1.0-beta.25 Time: 17516ms Asset ...

Tips for creating a string extension in TypeScript

Adding a custom method to a string in TypeScript can be achieved like so: const myPoint : string = "23"; const customNumber = myPoint.convertUsingMyCustomImplementation(); Attempting to define the method with a capital 'S' results in the followi ...