Pausing repetitive HTTP requests in an Angular 6 project within a do while loop

While waiting for the completion of one API call, I am recursively consuming an external API. The http calls are being made using

import {HttpClient} from '@angular/common/http'

As a newcomer to the framework, there may be something wrong in the code but the workflow is as follows:

The initial API call is made by this block of code:

initializeCrawling(): void {         
this.callCrawlInitializingAPI()       // this method is calling the api
  .subscribe(
    restItems => {
      this.groupCrawlingRestResponse = restItems;
      console.log(this.groupCrawlingRestResponse);
      this.isCrawlActive = false;
    }
  )

this.fetchResults();    // while callCrawlInitializingAPi call executes, this block here must executed on paralel.
}

I am now declaring a global

boolean

variable that will become false when this.callCrawlInitializingAPI() finishes executing.

Here is the code for the second API call which needs to be called recursively:

fetchResults(): void {
this.fetchDataApiCall()
  .subscribe(
    restItems => {
      this.groupCrawlingRestResponse = restItems;
      console.log(this.groupCrawlingRestResponse);
    }
  )
}

fetchDataApiCall() {
    do {
      this.http
        .get<any[]>(this.fetchResultsUrl, this.groupCrawlingResultRestResponse)
        .pipe(map(data => data));
      console.log("Delaying 3000");
    } while (this.isCrawlActive);
  }

The goal here is to introduce a delay in the do-while loop, perhaps by 1 second.

I have tried the following methods: 1 - Imported {delay} from "rxjs/internal/operators" and used it as shown above;

do {
  this.http
    .get<any[]>(this.fetchResultsUrl, this.groupCrawlingResultRestResponse)
    .pipe(map(data => data));
  console.log("Delaying 3000");
  delay(3000);
} while (this.isCrawlActive);

2- Used the setTimeout() function as follows:

do {
 setTimeout(function(){
 this.http
 .get<any[]>(this.fetchResultsUrl, this.groupCrawlingResultRestResponse)
 .pipe(map(data => data));}, 1000)
 } while (this.isCrawlActive)

None of these approaches seem to be working, and the do-while loop does not appear to be delayed, leading to multiple calls being processed continuously within the loop.

Primarily, I would like to know how to make it work, and secondly, if there's a better way of achieving this with Angular considering my beginner status with the framework.

Thank you


UPDATE

If anyone searches for this issue in the future, my question has a correct answer.

The only modification I had to make was in this line of code clearInterval(intervalHolder.id)

Answer №1

Before subscribing to a function with an http event, make sure that the function returns the stream/http-call.

fetchDataApiCall() {
  return this.http
    .get<any[]>(this.fetchResultsUrl, this.groupCrawlingResultRestResponse)
    .pipe(map(data => data));
  }

If you need to delay the response, include the delay operator in the pipe as shown below.

fetchDataApiCall() {
  return this.http
    .get<any[]>(this.fetchResultsUrl, this.groupCrawlingResultRestResponse)
    .pipe(map(data => data),
          delay(3000));
  }

UPDATE

Prior to the update, there were issues with the clear interval. Here is a fully tested solution for the problem. The first code block contains the polling logic where new requests are made every 500 ms as long as the isActive property remains true.

The second code block represents the service that simulates these requests.

export class ChildOne {
  longReqData;
  shortReqData = [];

  active = true;

  constructor(private requester: RequesterService) {}

  loadData() {
    this.requester.startLongRequest().subscribe(res => {
      this.longReqData = res;
      console.log(res);
      this.active = false;
    });

    let interval = Observable.interval(500);

    let sub = interval.subscribe(() => {
      this.requester.startShortRequest().subscribe(res => {
        this.shortReqData.push(res);
        console.log(res);
      });
      if (this.active === false) {
        sub.unsubscribe();
      }
    });
  }
}

@Injectable()
export class RequesterService {
  private counter = 0;
  stop() {
    this.subject.next(false);
  }
  startShortRequest() {
    this.counter += 1;
    let data = {
      delay: 0,
      payload: {
        json: this.counter
      }
    };
    return this.mockRequest(data);
  }

  startLongRequest() {
    let data = {
      delay: 3000,
      payload: {
        json: "someJSON"
      }
    };
    return this.mockRequest(data);
  }
  mockRequest(data) {
    return Observable.of(data).pipe(delay(data.delay));
  }
}

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

Show specific content based on which button is selected in HTML

I am working on a project where I have three buttons in HTML - orders, products, and supplier. The goal is to display different content based on which button the user clicks: orders, products, or supplier information. function showData(parameter){ i ...

What is the best way to display the nested information from products.productId?

How do I display the title and img of each product under the product.productId and show it in a table? I attempted to store the recent transaction in another state and map it, but it only displayed the most recent one. How can I save the projected informa ...

Perform an HTTP POST request in Angular to retrieve the response data as a JSON object

I am currently in the process of developing a simple user authentication app. After completing the backend setup with Node.js and Passport, I implemented a feature to return JSON responses based on successful or failed authentication attempts. router.pos ...

Issue with sending multiple files using FormData and axios in Vuex with Laravel. Server side consistently receiving null. Need help troubleshooting the problem

After trying the solution from my previous question Vuex + Laravel. Why axios sends any values but only not that one, which come's with method's parameter?, I realized that it only works when passing a single argument in axios. I managed to succe ...

Combining Mouseover and Click Events in Vue JS

Having four pictures, I want to display a specific component when hovering over them. However, I also need to bind the click event so that clicking on the picture will reveal the component. The challenge is that I am unable to simultaneously bind two event ...

Choosing dynamically created components:Making a choice among elements that are generated

Currently, I am working on a task that involves moving list items between two separate lists and then returning them back upon a click event trigger. Below is a snippet of the basic HTML structure: Unchosen: <br> <ul id="unchosen"></ul> ...

Mocha struggles to locate the ID within an input field - react-native

I am attempting to retrieve the text of an input using the .text() method in Selenium. However, every time I try to locate the element, it says that the specified ID was not found. (I am working with the Input component from NativeBase, but I have also te ...

Determine the duration of a trip based on the coordinates of two locations using angular Google Maps

I have successfully integrated angular google maps into my project. Utilizing the <agm-direction> component to showcase directions on the map. Now, my goal is to calculate the travel time by bike between two sets of latitude and longitude coordinat ...

Angular 10 does not reflect changes in the array when they occur

My component receives an array of offers from an Observable. However, when the list is modified (a offer is deleted), the component's list does not update accordingly. I attempted to use ngOnChanges to resubscribe to the list and update it in my comp ...

Trigger useEffect after prop has been changed

I'm trying to figure out how I can avoid running an API call in my component on initial rendering. The prop needed for the API call should be updated only after a form submission. Although I have included the prop in the dependency array of useEffect, ...

Encountering errors when examining local variables during unit testing on an Angular component

If we have 2 components, namely AppComponent and TestComponent. The TestComponent is being called using its directive in the HTML template of the AppComponent. Within the TestComponent, there is an @Input() property named myTitle. Unit testing is being pe ...

Using Vue.js, learn how to target a specific clicked component and update its state accordingly

One of the challenges I'm facing is with a dropdown component that is used multiple times on a single page. Each dropdown contains various options, allowing users to select more than one option at a time. The issue arises when the page refreshes afte ...

Tips for effectively managing index positions within a dual ngFor loop in Angular

I'm working on a feedback form that includes multiple questions with the same set of multiple choice answers. Here's how I've set it up: options: string[] = ['Excellent', 'Fair', 'Good', 'Poor']; q ...

Troubleshooting: Error in angular JavaScript due to minification: $injector:modulerr Module Error

After defining my angular code as shown below, I encountered an issue when trying to minify the javascript. The error message displayed was: $injector:modulerr Module Error. angular.module('myModule').controller('MyController', functio ...

Modify the button's border color upon click action

I am looking to implement a feature where the border of a button changes when clicked once and reverts back when clicked again. This should apply individually to each of the 16 buttons with the same class. Additionally, I want to enable the ability to clic ...

What is the best way to assign default values when destructuring interfaces within interfaces in TypeScript?

My goal here is to create a function that can be used with or without arguments. If arguments are provided, it should work with those values; if not, default values should be used. The issue I'm facing is that although there are no TypeScript errors ...

AngularJS global AJAX loader for managing $http requests across the application

I am currently working on an AngularJS app and I am looking for a way to include an ajax loader for each request made using $http. Is there a straightforward method to achieve this? My current solution involves setting $rootScope.loading to 1 every time I ...

What is the best way to switch the CSS class of a single element with a click in Angular 2

When I receive data from an API, I am showcasing specific items for female and male age groups on a webpage using the code snippet below: <ng-container *ngFor="let event of day.availableEvents"> {{ event.name }} <br> <n ...

Ways to validate a foreign key in Strongloop?

I am faced with a situation where I have a collection of categories and a separate collection of places, with each place having a foreign key that corresponds to a category ID. You can find the list of categories in categorie.json: http://pastebin.com/ttu ...

Ionic datetime returns default values upon initialization

I'm currently in the process of developing an Ionic-Angular-app. I require a datetime component on a page to set the creation date of an object. I am using formGroup for this purpose, but whenever I choose a different date, it always reverts back to t ...