Retrieve the final result from an observable after making several requests

In my application, there is a service layer that manages data and delivers it to components with the same value.

When the value of isProcessed is false, I need to send requests to the API. The service will make 10 attempts every half a second.

If the requests fail during the attempts, only 3 more requests will be made.

Once isProcessed becomes true, all pending requests should stop.

The logic for this functionality is already implemented, but I am facing an issue where I cannot output the last observable value received. All responses are being sent instead.

Requests are being made using observables, whether the value is false or true, but I am interested in capturing only the last response.

https://i.sstatic.net/mJjQh.png

All responses from requests are being received by the component, not just the last one

This is the service responsible for accessing the API:

public getPositionConsolidate(): Observable<PosicaoConsolidada> {       
    return this.http.get<PosicaoConsolidada>(`${environment.api.basePosicaoConsolidada}/consolidado`)
      .pipe(
        map(res => res),
        retryWhen(genericRetryStrategy()),
        shareReplay(1),
        catchError(err => {
            console.log('Error in Position Consolidate', err);
            return throwError(err);
        })
    )
}

This is the service responsible for managing data and delivering it to the component:

public positionConsolidate() {
    let subject = new BehaviorSubject<any>([]);
    this.api.getPositionConsolidate().subscribe(response => {
        if(response.hasProcessado == false) {
            for (let numberRequest = 0; numberRequest < 10; numberRequest++) {
                setTimeout(() => {
                   //subject.next(this.api.getPosicaoConsolidada().subscribe());
                   this.api.getPositionConsolidate().subscribe(res => {
                        subject.next(res)
                   })
                }, numberRequest * 500, numberRequest);
            }
        } else {
            retryWhen(genericRetryStrategy()),
            finalize(() => this.loadingService.loadingOff())
        }   
    })
    return subject.asObservable()
}

In the component:

public ngOnInit() {
 this.coreState.positionConsolidate().subscribe(res => console.log(res))
}

Answer №1

If you're looking to grab the last emission from an observable, the last operator is the way to go. Your current code structure can be reorganized into a single stream without any non-rxjs control structures for better integration.

public positionConsolidate() {

  return this.api.getPositionConsolidate().pipe(
    concatMap(res => iif(() => res.hasProcessado,
      of(res),
      interval(500).pipe(
        take(10),
        concatMap(() => this.api.getPositionConsolidate())
      )
    )),
    retryWhen(genericRetryStrategy()),
    finalize(() => this.loadingService.loadingOff()),
    last()
  );
}

Here's what's going on:

  • The initial API call is made first.
  • Then, depending on the result:
    • The initial result is returned.
    • Or the API is called 10 times every 500ms.
  • Your logic for retryWhen and finalize is implemented.
  • The final emitted result is returned.

Avoid nesting subscriptions within observables - utilize higher order observables like concatMap instead.

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

What is the best way to trigger an AJAX request when a user navigates away from a webpage or closes the

The Challenge at Hand Greetings, I am currently developing a database-driven game that involves users answering questions and earning the right to change the question by providing the correct answer. However, I have encountered a significant issue which ...

Using Vue.js to bind data in two directions by using an object with v-for

I can't seem to get input data properly bound to object properties. When I try to iterate through an object to create input fields based on its attributes, the v-model data binding doesn't seem to be working as expected. Even with the code below, ...

Checking for different elements between two arrays in AngularJS can be achieved by iterating through

I am working with two arrays: $scope.blinkingBoxes=[1,3,2] In addition, I have another array named $scope.clickedBoxes where I push several values. Currently, I use the following code to determine if the arrays are identical: if(angular.equals($scope.bli ...

Is there a Typescript function error that occurs when attempting to rename a key, stating it "could potentially be instantiated with a different subtype"?

I am currently working on a Mongoify type that accepts a type T, removes the id key, and replaces it with an _id key. type Mongoify<T extends {id: string}> = Omit<T, "id"> & { _id: ObjectId }; function fromMongo<T extends ...

What is the process for removing an added message using jQuery after it has been appended by clicking the same button?

https://i.stack.imgur.com/YsmKZ.pnghttps://i.stack.imgur.com/dW2lo.pngI have searched extensively through previously asked questions without success. My goal is to remove the previous appended message when the submit button is clicked again. This functiona ...

What prevents the creation of an Angular app without any content?

Why am I unable to create an empty Angular app? I have been following the guidelines provided on the official documentation: https://angular.io/guide/setup-local. To start off, I installed Angular using the command: npm install -g @angular/cli. Now, whe ...

Why does AngularJS keep showing me an "Argument 'HomeController' is not a function" message?

I am currently in the process of developing a Cordova application and I plan to utilize Angular for creating pages that will be displayed based on user selections. At the moment, I am working on this in a web environment before transitioning to Cordova. & ...

Angular is generating local caches of NPM packages within the designated .angular folder

Is there a way to turn off the caching in the main Angular project directory? I noticed this issue after setting up NVM last week. https://i.sstatic.net/zFnGy.png ...

Determine the number of selected checkboxes within the gridview

Looking for a way to tally up the checked checkboxes within my gridview, but not sure of the best approach. Perhaps utilizing JavaScript to achieve this and storing the count in a hidden textbox could be a viable solution. Any suggestions on how to tackl ...

Prolong the Slide Duration in Slider Pro Slideshow

I am currently utilizing Slider Pro from bqworks.com for a slideshow with automated cycling on my website. I would like to adjust the display duration of each image in the slideshow. The documentation mentions a property called "slideAnimationDuration," wh ...

How to incorporate HTML 5 video into your Angular 2 project using Typescript

How can I programmatically start an HTML video in TypeScript when the user clicks on the video area itself? Below is my HTML code: <div class="video"> <video controls (click)="toggleVideo()" id="videoPlayer"> <source src="{{videoSource ...

Simultaneously removing and inserting components with Meteor.js

I have a straightforward set of items that is displayed like this {{#each items}} {{> item}} {{/each}} My code defines that only the three most recent items are shown return Items.find({}, {sort: {timestamp: -1}, limit: 3}) Whenever a new item i ...

What is the method to retrieve just plain text (String) from an Ajax URL response?

I'm still learning how to use Ajax. My current project involves populating a dropdown based on the selected value from another dropdown in HTML. The issue I'm facing is that, while I am able to get the desired output, it includes unwanted HTML fo ...

Steps to convert a phone number into JSON format

The primary focus Upon receiving an MQTT packet, it is displayed as an ASCII array in the buffer after being printed using stringify: packet = { "cmd": "publish", "retain": true, "qos": 1, "dup& ...

Create a JavaScript function that performs multiplication and returns two distinct calculations

Upon examination of the embedded script below, I noticed that it is only providing a single result (500). How can I modify my code to generate both results? Your advice on this matter is greatly appreciated. function multiplier() { var number = 2 ...

How can I effectively exclude API keys from commits in Express by implementing a .gitignore file?

Currently, my API keys are stored in the routes/index.js file of my express app. I'm thinking that I should transfer these keys to an object in a new file located in the parent directory of the app (keys.js), and then include this file in my routes/in ...

Tips for organizing a JSON request

When making a call to an endpoint using Axios, the response structure may look something like this: items: [ { url: "https://api.example1...", expirationDate: "2019-11-15T00:00:00+01:00" }, { url: "https://api.example2...", expirationDate: "2019-12-20T00: ...

What is the best way to incorporate rows from JSON data into my table?

I have a backend function that returns a JSON file containing values. I need to extract specific information from this JSON data and populate input fields within a table dynamically, based on the amount of data retrieved. Example JSON Data [ { "Type ...

Encountering a TypeError indicating that the asterisk is not functioning as a proper function

Whenever I run my server.js file, an error keeps popping up: TypeError: routing is not a function This occurs in the following line of code: routing(app); In my routing.js file, the content looks like this: // JavaScript source code var friends = requ ...

typescript limiting the keys in an index signature

Exploring TS index signature examples and noticing inconsistencies in key restriction behavior. const s = Symbol(); type DictNumber = { [key: number]: string; } const dictNumber: DictNumber ={ 1: 'andy', // no error, as intended. 'fo ...