The issue of Angular finalize not functioning when used within a pipe alongside switchMap

Once the user confirms, I want the process to begin and keep the modal busy until it's complete. However, the current code does not function in this manner. The isModalBusy condition only turns false when an HTTP error is returned from the service. In all other cases, it remains true.

run() {
        let inputParams = JSON.stringify(this.paramsInput);

        this.confirmation.warn(
            'RunConfirmationMessage',
            'AreYouSure',
            {messageLocalizationParams: []}
        ).pipe(
            // take(1)  when i put take(1) here it works tho,
            filter(status => status === Confirmation.Status.confirm),
            switchMap(() => {
                this.workOutput = {
                    success: true,
                    consoleOutput: "Executing now..."
                }
                this.activeTabId = 1;
                this.isModalBusy = true;
                return this.processService.doWork({work: this.work, workParams: inputParams});
            }),
            finalize(() => {
                this.isModalBusy = false
            }),
        ).subscribe({
            next: (result) => this.workOutput = result,
            error: (error: HttpErrorResponse) => this.workOutput = {success: false, errorMessage: error.message} as WorkOutput,
        });
    }

I obtained this code from the theme documentation I am using, and I am unsure about the purpose of mapSwitch in this context. Any clarification on why this is used and how to make it function as intended would be greatly appreciated.

Answer №1

@Andreas is correct in explaining why take(1) works as intended. Providing additional context on the functionality of switchMap, the output of this.confirmation.warn is an Observable stream (presumably of type Observable<Confirmation> according to your code) which undergoes a transformation within the pipe.

Within your code, any values emitted by this.confirmation.warn will be processed by every operator defined within the pipe() block:

.pipe(
  // extracting the initial value emitted from warn()
  take(1),
  
  // filtering out any emissions unless they match the desired status
  filter(status => status === Confirmation.Status.confirm),
  
  // switchMap alters the focus of the stream - this pipe no longer tracks 
  // the value emitted by warn() but instead switches to a different observable. 
  // The output returned by doWork() will continue down the pipe.
  switchMap(() => {
    this.workOutput = {
      success: true,
      consoleOutput: "Executing now..."
    }
    this.activeTabId = 1;
    this.isModalBusy = true;
    return this.processService.doWork({work: this.work, workParams: inputParams});
  }),

  // upon completion of the Observable, this operator will execute. take(1)
  // ensures only one value is evaluated before the Observable completes.
  // 
  // this may not be necessary if utilizing the `complete` function within the
  // subscribe block as demonstrated in the next example
  finalize(()=> {
    this.isModalBusy=false
  }),
)

To update isModalBusy regardless of the outcome, you can include it in both the complete and error functions within your subscription:

  subscribe({
   // executed after each emission from the pipe
   next: (result)=>this.workOutput = result,
   
   // error handling already implemented for the pipe
   error: (error: HttpErrorResponse)>{
     
     // ensuring proper handling of isModalBusy
     this.isModalBusy=false;

     return this.workOutput={success:false,errorMessage:error.message} as WorkOutput,
     }
   }),

  // akin to finalize, any actions here will occur _once_ upon successful 
  // completion of the observable.
  complete:>{
    this.isModalBusy=false;
  })

Answer №2

For the finalize function to be executed, it is necessary for the observable to reach completion. This is why using take 1 in your case works effectively. When you use take 1, the stream will emit one value and then immediately terminate (Take emits provided number of values before completing). In the scenario you presented, the observable does not complete, as your subscription is still waiting for additional values.

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

Issue with Angular 6: Dynamic Meta tag malfunctioning while sharing page on Facebook with og:description tag

I am facing an issue where I want to update the meta tags dynamically using API calls. The updated data shows correctly when inspected, but when sharing the link on Facebook, it does not reflect the changes. Index.html <meta name="description" conte ...

Creating an error message display function using HTML and JavaScript when incorrect input is detected

I am having trouble creating an HTML5 and JS program that will show an error message if the user input is empty. Despite my efforts, I can't seem to get the "Error Message" to display. As a beginner, the video tutorial I'm following doesn't ...

The ActionController is encountering an UnknownFormat error when trying to respond to AJAX requests with js using

I've been scouring the internet for information on this topic, but I'm having trouble understanding how AJAX works with Rails. I've gone through the documentation multiple times and it's just not clicking for me. From what I gather, AJ ...

Is it possible to run npm scripts directly?

There is a script in my package.json file "start": "cross-env NODE_ENV=development PORT=3000 CODE_SPLIT=0 node ./react-imvc/bin/www-babel-register", I need to run the script with the --inspect flag, but I am unable to modify the package.json. I would lik ...

Exploring the effectiveness of testing Svelte components

Looking to test a component that utilizes a third-party module without mocking the imported components? Check out this example: // test.spec.ts import Component from "Component"; describe('Component', () => { test('shoul ...

Using the Express router: Error occurred - Router.use() function expected a middleware function but received an Object instead

After searching through numerous questions on SO, I still haven't found a solution to my issue. routes/authentication/index.js import { Router } from 'express' const router = Router(); router.get('/', (_req, _res) => console. ...

Cross-domain scripting

I have a unique javascript code hosted on my server. I want to offer website visitors a similar implementation approach to Google Analytics where they can easily embed the script on their servers. For instance: <script type="text/javascript" src="http: ...

I am trying to set a background image specifically for one page in my application, but I am struggling to make it work. As a newcomer, I am still learning how to

I've been working on the code for a login page, but I'm having trouble setting a background image for the page. I know how to set it for the whole application by modifying the app component, but when I try to do the same for this specific compone ...

The perplexing paradox of THREE.js line thickness

Upon reviewing the LineBasicMaterial THREE documentation, I came across a note stating that on Windows systems, the linewidth is automatically set to 1 and cannot be adjusted. Interestingly, there is a fascinating example on threejs.org utilizing the same ...

Using JQuery to Send Form Data with an Ajax POST Request

On my web Node/Express app, I have implemented a basic messaging service and am currently attempting to submit the form using Ajax with the FormData object. While the form submission works perfectly without Ajax, all the req.body values are undefined when ...

Need help incorporating a "section trail" into your website's navigation sidebar using JS/jquery? Here's how you can do it!

My website is quite extensive and contains numerous elements. There are times when I find myself wanting to navigate back and forth between different sections of the page. I've noticed that some websites have a feature called a "page trail," which di ...

Various modules in the project need to have distinct GitHub origins, particularly in the case of Spring-Angular

My goal is to create a well-structured project with separate frontend and backend modules. Here is the initial project structure: https://i.stack.imgur.com/EghPA.png I have attempted this in various configurations before, but every time I try, git recogn ...

The Alertify dialog vanished without being able to confirm

While working on some code, I encountered a specific issue: alertify.dialog("confirm").set( { 'labels': { ok: 'Personal', cancel: 'Share' }, 'message': 'Select target:', ...

Using Ajax to send a JSON object containing two arrays to a servlet, then parsing it in a Java servlet without the use

When sending data to a servlet, I utilize an Ajax POST call to send a JSON object containing two arrays. In the servlet class in Java, I need to read this data sent in two lists or arrays. I am avoiding the use of jQuery for the Ajax call and am not very f ...

The issue of module exports in node.js returning undefined needs to be resolved so that it correctly returns a MongoDB

I've previously used an app to create a blog site that pulls data from MongoDB. Now, I'm attempting to integrate it into a new personal website as a module. Unfortunately, I'm encountering an issue where the object being passed back to the a ...

Tips on how to remove the filter from a select element using Angular?

My code includes the following HTML: <select ng-options="mark.id as mark.name for mark in marks" ng-model="markSearch.mark.id"> <option value="">-- Choose mark --</option> </select> ... <tr ng-repeat-start="pipeType in pipeT ...

JavaScript: Techniques for extracting multiple digits from a text

Enter: "WASHINGTON (Reuters) U.S. stock index futures indicated a marginal recovery on Wall Street on Thursday, as futures for the S&P 500 rose by 0.34 percent, Dow Jones futures gained 0.12 percent, and Nasdaq 100 futures increased by 0.51 percent ...

Utilizing JavaScript libraries in a TypeScript project: A step-by-step guide

Currently, I am working on an existing TypeScript AngularJS project and looking to incorporate d3js. However, due to restrictions with the corporate proxy, I am unable to use tools for downloading or managing dependencies. As a result, I have opted for man ...

Error: WebStorm's Language Service has timed out while executing TSLint operations

While working on my Mac running MacOS Sierra with WebStorm (version 2017.2.4), I encounter a pop-up notification sporadically, as shown in the following image: https://i.sstatic.net/mdVtd.png My coworkers and I all have the same TSLint configuration and ...

Utilizing Jquery to Integrate Hashtags

I'm looking to implement a feature where any text I write starting with a # symbol automatically changes color to blue, and then returns to black once I hit the space key to end the text. I attempted to achieve this using the following logic within a ...