Angular - Execute function every 30 seconds while considering the duration of the function execution

In my Angular 7 application, I am utilizing RxJS to handle asynchronous operations.

My goal is to retrieve a list of items from an API endpoint every 30 seconds. However, there are times when the request may take longer than expected, and I want to ensure that the next call accounts for this delay.

For example, if the initial request takes 10 seconds to complete, I wish to make the subsequent request after 40 seconds (30 + 10), instead of just 20 seconds (30 - 10).

I have attempted to achieve this using the following code:


fetchList() {
   this.service.fetchListFromHttp()
      .pipe(
        finalize(() =>
          setTimeout(() => {
            this.fetchList();
          }, 30000)
        )
      )
      .subscribe(
         result => this.list = result,
         err => this.logError(err)
      );
}

However, I have noticed strange behavior where the function gets called at irregular intervals like every 10 seconds or 20 seconds, rather than consistently every 30 seconds as anticipated. I expect the interval between calls to always be greater than 30 seconds.

Answer №1

If you are the one who developed the backend, using socket.io may be the solution you're looking for to connect to your own backend.

Consider exploring the capabilities of RxJS which is integrated with Angular. With RxJS, you can achieve tasks like fetching data and pausing in between.

One approach could be:

this.service.fetchInfoFromHttp().pipe(delay(30 * 60 * 10000), () => ...), repeat(Infinity))

For more information on RxJS, refer to the following documentation links:

RxJS delay

RxJS repeat

Socket.io

EDIT: How Can I make a Timer using an observable in Angular 9

EDIT AGAIN:

Appreciate your input @goga-koreli, debounce feature might be suitable

https://www.learnrxjs.io/learn-rxjs/operators/filtering/debounce

Answer №2

To enhance the solution provided by SVNTY, you can implement it in the following way:

retrieveData() {
  const processAndWait = (data) => interval(30000).pipe(
    take(1),
    ignoreElements(), // necessary to disregard interval numbers
    startWith(data),
  )

  // fetch data from network, pass it to subscriber, and wait for specified time
  // repeat will trigger a new iteration when interval completes with take(1)
  this.service.fetchDataFromHttp().pipe(
    concatMap((data) => processAndWait(data)),
    repeat(Infinity), 
  ).subscribe();
}

Answer №3

Implement the use of observables from rxjs by following this tutorial

import { interval, Subject, PartialObserver, Observable } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

Once you have imported the necessary libraries, set the interval to 30 and start it. When it finishes, call your service and then restart the interval when the service gets the result.

ispause = new Subject();
private time = 30;
timer: Observable<number>;
timerObserver: PartialObserver<number>;

ngOnInit(){
    this.timer = interval(1000)
      .pipe(
        takeUntil(this.ispause)
      );    
    this.timerObserver = {
      next: (_: number) => {  
         if(this.time == 0){
           this.ispause.next;
           this.callservice();   
         }
         this.time -= 1;        
      }
    };
    this.timer.subscribe(this.timerObserver);    
}

callservice(){
  // Once data is retrieved
  this.service.fetchListFromHttp()
      .pipe(
        finalize(() =>
          this.time = 30;
          this.timer.subscribe(this.timerObserver);
        )
      )
      .subscribe(
         result => this.list = result,
         err => this.logError(err)
      );

 }

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

Having trouble passing a jQuery variable containing a string value to PHP through the jQuery AJAX function?

Below is the jQuery function code snippet: function processMessage() { if (textValue != "") { messageString='<div class="alert-box round"><p class="text-left">' + username + ':' + textValue + '</p>< ...

Create a custom button in Material-UI using Styled-components, and integrate it with React

I'm currently working on a project using React, TypeScript, and styled components along with the material-ui library. I have created styled material-ui buttons as shown below: import React from 'react' import styled from 'styled-compone ...

The alert feature does not seem to be functioning properly when displaying error messages

// Issue: Alert is not working on error message. I intend to only display up to four issues, after that it should not work. success: function(msg, String, jqXHR) { window.location = 'home.html'; $("#result").html(msg, String, jqX ...

Unable to display content on the ejs file

Currently, I have been diving into the world of node.js and exploring how to manipulate data by writing and reading from JSON files. It has been an interesting journey so far; however, I encountered a hiccup. Specifically, when attempting to post new data ...

Please enter a numerical value into the input field in a JavaScript form

<script> function loop() { var input = document.getElementById('inputId').value; for (var i = 0; i < input; i++) { var result = document.getElementById('outputDiv').innerHTML ...

Set up an event listener for a specific class within the cells of a table

After spending the last couple of days immersed in various web development resources, I find myself stuck on a particular issue. As someone new to this field, the learning curve is quite steep... Let's take a look at a single row in my project: < ...

express.static() fails to serve files from public directories when accessed via router paths other than "/"

Express static configuration: app.use(express.static(__dirname + "/public")); Directory Structure: --public --assets --js --[JavaScript scripts] --stylesheets --[CSS files] Defined Routes: const shopRoutes = require('./routes/shopRo ...

The custom component is not updating the NgIf directive in HTML even though it receives a boolean variable

I am struggling with a custom component that includes an *ngIf in its view to handle a boolean variable, but for some reason the *ngIf directive is not working. Here is the code snippet: Component @Input('title') titleText; @Input('backButt ...

NuxtJS (Vue) loop displaying inaccurate information

I have a dataset that includes multiple languages and their corresponding pages. export const myData = [ { id: 1, lang: "it", items: [ { id: 1, title: "IT Page1", }, { ...

The AJAX request encountered an error due to an Unexpected End of JSON Input

My AJAX code is encountering an error message. parsererror (index):75 SyntaxError: Unexpected end of JSON input at parse (<anonymous>) at Nb (jquery.min.js:4) at A (jquery.min.js:4) at XMLHttpRequest.<anonymous> (jquery.min.js: ...

Node.js unleashes the power of Ajax

I have seen some people ask this question before, but I am having trouble understanding the responses :/ I am working with node.js and really want to utilize Ajax in my project. Here is a snippet of my code: var $ = require('jquery'); var http ...

transforming an array of undefined values into an array of strings

I am attempting to transfer an array value from the frontend to the backend, but I am encountering errors during the process. Below is the response data: { sender: 'venkat', numbers: '[919361667266, 919361667266, 919361667266, 919361667 ...

Is the Scope Staying Static in AngularJS 1.4 when Input Text Changes and Two-Way Binding is Enabled?

Encountering a strange issue with AngularJS 1.4 (TypeScript). The problem lies within the controller where a variable is set and displayed in an input text box. Oddly, when attempting to edit the value in this text box and clicking on a button, the variabl ...

JavaScript Empty Input Field when Duplicating Node

I am seeking advice on how to clear the textboxes when an HTML form is cleared. The following JS code runs onclick: var counter = 0; function moreField() { counter++; var newFields = document.getElementById('readroot').cloneN ...

Express.js never terminates a session

I have a Backbone View that makes an Ajax call to the server to delete a session. Upon triggering the following event on the server: app.delete('/session', function(req, res) { if (req.session) { req.session.destroy(function() { ...

Is there a way for me to adjust the typography background based on its current status?

Is there a way to dynamically adjust the background color of text based on the status value? Currently, when the status is pending, the background color defaults to yellow. For example, if the status changes to complete, I want the background color to ch ...

Troubleshooting JavaScript: Dealing with JSON Import Issues Involving Arrays of Objects

I'm encountering an issue while trying to import a JSON file that contains an array of blog-posts. Although all the data from the JSON file is successfully imported, I am facing troubles with accessing the Array of objects (edges). This specific code ...

The tweet button feature does not give users the ability to make changes to the content

When using the "Tweet Button" feature, users will follow these steps: The user clicks on the Tweet Button If not already logged in, the user is prompted to login to their Twitter account. New users can also create an account at this stage. The Shar ...

Utilizing an object's value as a key for a separate object

Here's an overview of my current object structure: import { imageOne, imageTwo } from "./images"; export const imageKeyMap = { "one": imageOne, "two": imageTwo } The definitions for imageOne and imageTwo ...

I am in need of a blank selection option using an md-select element, and I specifically do not want it to be

I'm currently utilizing Angular Material with md-select and I am in need of creating a blank option that, when selected, results in no value being displayed in the select dropdown. If this blank option is set as required, I would like it to return fal ...