Tips on displaying a spinner only when data is retrieved from an Http service

How can I ensure that a spinner is only shown during an HTTP service call and dismissed when my component receives data?

To address this issue, I implemented a cache service to store data fetched from the HTTP service for future use. However, I want to show the spinner only during the initial HTTP call and not when data is fetched from the cache.

While the service functions correctly, the spinner continues to display even when data is retrieved from the cache. Is there a way to trigger the spinner display only during HTTP calls and not when fetching cached data?

In the code snippet below, the presentLoading() method gets called in ngOnInit, so it runs every time. How can I modify it to only execute when fetching data from the cache?


    ngOnInit() {
       this.presentLoading();
       this.CategoryCtrl();
     }

     CategoryCtrl() {
       this.serverService.getReviewsCategory(this.id)
       .subscribe((data) => {
         this.category_sources = data['value'];
         this.stopLoading();
       });
     }

     async presentLoading() {
       const loadingController = this.loadingController;

       const loadingElement = await loadingController.create({
         spinner: 'crescent',
       });
       return await loadingElement.present()
     }

     async stopLoading() {
       return await this.loadingController.dismiss();
     }

   }

EDIT1: This is the CacheService:


    import { Injectable } from '@angular/core';

    @Injectable({
      providedIn: 'root'
    })
    export class CachingService {

      constructor() { }

      private _cache = {};

      isCached(url: string) {
        return this._cache[url];
      }

      getData(url: string) {
        return this._cache[url];
      }

      setData(url) {
        return (data) => {
          if (data && (data instanceof Error) === false) {
            this._cache[url] = data;
          };
        }
      }

      reset() {
        this._cache = {};
      }
    }

This is the server service's method:



     getReviewsCategory(cat_id) : Observable<any> {
      if (this._c.isCached(url)) {
            return of(this._c.getData(url));
          }else{
            var modeapp = window.sessionStorage.modeapp;
            var typemodeapp = typeof(window.sessionStorage.modeapp);
            if (modeapp === "online") {
              let promise = new Promise ((resolve, reject) => {
                this.httpNative.get(url, {}, {}).
                then((data) => {
                  let mydata = JSON.parse(data.data);
                  console.log("Data from HTTP: ");
                  console.log(mydata);
                  resolve(mydata);
                }, (error) => {
                  console.log("error in HTTP");
                  reject(error.error);
               }
              );
            });
              var observable = from(promise);
          }
        }
        return observable
        .pipe(
          tap(this._c.setData(url))
        );

Answer №1

It appears that you are returning an observable from the service. To address any issues, you can attempt the following solution.

     CategoryCtrl() {
       this.serverService.getReviewsCategory(this.id)
       .subscribe((data) => {
         this.category_sources = data['value'];
         this.stopLoading();
       },
       (error) => console.log(error),
       () => this.stopLoading(); // This will always be executed
     );}

Documentation: http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-subscribe

On a related note, it is worth noting that the problem could be stemming from how you are calling .dismiss() on the object. Ensure you are invoking dismiss on the correct instance of the element and not the object itself.

let loadingElement: Loading = null;

async presentLoading() {
   const loadingController = this.loadingController;
   this.loadingElement = await loadingController.create({
     spinner: 'crescent',
   });
   return await loadingElement.present()
}

async stopLoading() {
   return await this.loadingElement.dismiss();
}

Answer №2

If you want to manage http requests in Angular, one effective way is to use an HttpInterceptor class. This allows you to intercept all outgoing HTTP calls and perform actions like displaying a spinner while waiting for a response.

The basic structure of using an HttpInterceptor is as follows:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // Display spinner
    return next.handle(req).pipe(
        map((event: HttpEvent<any>) => {
            if (event instanceof HttpResponse) {
                // Hide spinner
            }
            return event;
        })
    );

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

Ways to initiate an HTTP request within switchMap upon emission of a BehaviorSubject value

As I delve into writing angular applications in a declarative style, I find myself pondering on the most effective approach for handling POST requests. Specifically, I am facing a dilemma with regards to calling these requests when dealing with a login for ...

Ways to assign an id to an element when the body includes a specific class and the element id includes a class

In this scenario, the code is designed to assign the class "active" to the element with the ID "39" under two specific conditions. Firstly, the body must contain the class "hotel-stores", which can come in variations like hotel-stores, hotel-stores-1, hote ...

Using jQuery AJAX to Populate a Textbox and Dropdown Menu

I am new to using JQuery AJAX, so I am still learning the syntax. Currently, I am retrieving values from a database and populating a dropdown box. What I would like AJAX to do is fill in three other fields with hardcoded information when a selection is mad ...

Angular http request causing swiper to malfunction

I'm currently working on a project using Angular 9 and I've encountered an issue with integrating Swiper while utilizing *ngFor. Surprisingly, Swiper functions perfectly without any HTTP calls. However, as soon as I introduce an HTTP call, Swiper ...

The useEffect hook in ReactJs is triggering multiple times

Encountering challenges while developing an Infinite scroll using ReactJs and Intersection observer API. Upon initial application load, the API gets called twice instead of once. This behavior may be due to strict mode, although not confirmed. Additionall ...

The issue I'm facing with the change handler for the semantic-ui-react checkbox in a React+Typescript project

Hey there! I'm currently facing an issue with two semantic-ui-react checkboxes. Whenever I try to attach change handlers to them, I end up getting a value of 'undefined' when I console log it. My goal is to retrieve the values of both check ...

Steps for creating a two-dimensional arc

I want to input some pre-determined acr values from another program and replicate them in three.js Currently, I'm using code I found on this site to draw the arc, although it might not be the most optimal solution. function DRAWarc(){ ...

Streaming the request body in NodeJS using ExpressJS without buffering

Looking for a solution to process requests with no specified content-type as binary files. const app = express(); app.use(bodyParser.raw({type: (req) => !req.headers['content-type'], limit: '500mb' })); Some of these files can be ...

The AutoComplete feature of MaterialUI Component fails to function properly even when there is available data

I am facing an issue with my component as it is not displaying the autosuggestions correctly. Despite having data available and passing it to the component through the suggestions prop while utilizing the Material UI AutoComplete component feature here, I ...

The behavior of Datatables varies depending on the screen resolution

In my data table, there are numerous entries with child tables on each row of the main table. I am currently in the process of incorporating this type of functionality into my table, with a few modifications to create a table within the child row. You can ...

Conceal an item if it is located past a certain point (from the viewpoint of the camera)

In the realm of three-dimensional space, imagine a cube represented by a THREE.Mesh that has been added to the scene. cube.position.set( 10, 10, 10 ); scene.add( cube ); Once you have rotated the scene using your mouse, the goal is to cleverly conceal th ...

Stealthy Google Recaptcha integrated with a dynamic AJAX form

My website includes an ajax form: <form id="my_form"> <input type="text" id="field1" /> <input type="submit" value="submit" /> </form> I also have this JavaScript code: document.getElementById("my_form").onsubmit = fu ...

Utilizing PHP and Ajax for paginating JSON responses

I have successfully parsed some JSON data from the YouTube API, but I am running into a limitation where only 50 results can be shown per request. I am looking for help on how to implement pagination using either JavaScript or Ajax in my PHP script. The go ...

Is there a method available to define a custom auto-generated key when inserting an object into Firebase Realtime Database?

I've been working on pushing data to the firebase rtdb and I want to make sure I can easily access it from other places. Here's the code snippet that I'm using to add data to the rtdb: function addStudentHandler(studentData) { fetch( ...

Typescript's default string types offer a versatile approach to defining string values

Here is an example code snippet to consider: type PredefinedStrings = 'test' | 'otherTest'; interface MyObject { type: string | PredefinedStrings; } The interface MyObject has a single property called type, which can be one of the ...

Choose the div without a class

I currently have several divs displayed on my website. <div class="slide bx-clone"></div> <div class="slide"></div> <div class="slide"></div> <div class="slide bx-clone"></div> <div class="slide bx-clone" ...

Ensuring TypeScript recognizes a class property as definitively initialized when set using a Promise constructor

I have a simple class definition that is giving me an error in TypeScript. class Container { resolveData: (s: string) => void // not definitely initialized error! data: Promise<string> constructor() { this.data = new Promise&l ...

What is the mechanism through which the subtraction operator initiates the conversion of an array to a

Here are a couple of examples showcasing my code. Let's start with the first one: console.log([4] + 10); //"410" It is commonly known that the addition operator can only work with numbers and strings. Therefore, in this case, [4] needs to b ...

What could be causing my Jquery fade effect to not function properly?

I'm new to incorporating Jquery into my website and I'm facing an issue with getting the first row of pictures to fade in (upwards) when scrolling. Despite my efforts, they are not behaving as expected. Any guidance on how to resolve this? HTML: ...

The color of the three js cube is charcoal, definitely not a fiery red

Just dipping my toes into the world of three.js...my cube is displaying in black even though I set the color to red. Any ideas why? <!DOCTYPE html> <html> <head> <title>Experimenting with shapes</title> & ...