Steer clear of receiving null values from asynchronous requests running in the background

When a user logs in, I have a request that retrieves a large dataset which takes around 15 seconds to return. My goal is to make this request upon login so that when the user navigates to the page where this data is loaded, they can either see it instantly if the request has completed, or only wait a few seconds for it to finish.

In order to achieve this, once the user successfully logs in, I trigger the request for the large dataset:

this.getDataService.getAsyncData(data.LinkToken); // Initiate request from data service

The retrieved data is then saved into local storage and made available for retrieval when the user lands on the corresponding route triggering that request through ngOnInit()

getAsyncData(linkToken){ // Background request loading while user navigates
   this.httpC.get(this.baseUrl + "/AccountInfo/Data?linkToken=" + linkToken + "&deliveryTypeId=" + 0 + "&pickupLocationId=" + 0 + "&paymentTypeId=" + 0).map((res:Response) => res.json()).subscribe(res => {
       this.asycCollection = res;
       this.globalService.setData(this.asycCollection) // Store data in local storage
       console.log(this.asycCollection);
    })
}

Subsequently, this data can be retrieved as a promise request within the component once the route loads

// Set local storage with the data
setData(refillObject:any){ 
    this.refillObj = refillObject;
    window.localStorage.setItem("refillData", JSON.stringify(this.refillObj))
}
// Retrieve promise of the background async call
getData(){
    let refillInformation:any = window.localStorage.getItem("refillData");

    return new Promise<any>((resolve, reject) => resolve(refillInformation));
}

Now, the challenge is ensuring that the data is only retrieved after it has finished loading, without causing any issues. If the user quickly navigates to the page before the data has finished loading, it returns null and causes errors. However, if they return after the data has finished loading, everything works smoothly as intended.

So, how can I effectively wait and retrieve the data only once it has finished loading? Remember, this data was originally fetched as a background async request upon user login and is now being accessed from local storage rather than making a new request to the REST Service.

Component Code:

getAsyncRefills(success){
    this.globalService.getData().then(data => { // The code below will throw errors if the page is loaded before the data request completes and stores in local storage.
        this.orderData = JSON.parse(data);
this.currentDeliveryType = this.orderData.DeliveryTypes.find((item) => 
item.DeliveryTypeId == this.orderData.DeliveryTypeId);
        this.currentPaymentArr = this.currentDeliveryType.PaymentTypes;
        this.currentPickupLocations = this.currentDeliveryType.PickupLocations;


        this.setOptions();
        this.buildOrders();

    })

}

Answer №1

If confronted with this issue, my strategy to tackle it would involve:

Establishing a service with the task of:

  • initiating the heavy query execution on the backend
  • making an Observable available as a public property that signals when the query results are ready
    • upon receiving data from the backend, the Observable publicly exposes the data

This specialized service is implemented using Dependency Injection, connecting it to both the login component and the data display component.

After a successful login, the login component triggers the service's query initiation method.

The data display component can access the public Observable provided by the service to present the data upon arrival. Methods like utilizing Angular's async pipe in the template or subscribing to the Observable and executing the required logic within the subscription can be used for this purpose.

Answer №2

When dealing with a scenario like this, I prefer not to use local storage but opt for using a service instead (apologies for any coding imperfections as I don't have an IDE).

@Injectable()
export class ExpensiveDataStore {

  private expensiveData_: ConnectableObservable<ExpensiveThing>;
  private connection: Subscription;

  get expensiveData(): Observable<ExpensiveThing> {
    if(!this.expensiveData_) {
      throw Error('Must initialize store first!');
    }
    return this.expensiveData_;
  }

  initialize() {
    this.expensiveData_ = this.goFetchExpensiveData().publishLast();
    this.connection = this.expensiveData.connect();
  }

  void reset() {
    this.connection.unsubscribe();
    this.connection = this.expensiveData.connect();
  }

}

In your app.component.ts or any other high-level component, you can invoke the initialize() method. Then, in the component requiring the data, simply subscribe to expensiveData.

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

Is it possible to devise a universal click handler in TypeScript that will consistently execute after all other click handlers?

In my ReactJS based application written in TypeScript, we have implemented various click handlers. Different teams contribute to the application and can add their own handlers as well. The challenge we face is ensuring that a specific global click handler ...

Challenges faced while addressing angular package.json dependencies for a live build

For several hours now, I've been struggling to make npm run build:production work. This command is included as part of my build process when a branch is pushed. However, I have encountered an issue with my package.json file that I haven't been ab ...

Setting a random number as an id in the constructor in Next JS can be achieved by generating a

What steps can be taken to resolve the error message displayed below? Error: The text content does not match the HTML rendered by the server. For more information, visit: https://nextjs.org/docs/messages/react-hydration-error Provided below is the code i ...

Capturing Data from Tables and Saving it with Protractor

Imagine having a table structured like this <h2>HTML Table</h2> <table> <tr> <th>Company</th> <th>Contact</th> <th>Code</th> </tr> <tr> <td>Alfreds Fu ...

Apply a see-through overlay onto the YouTube player and prevent the use of the right-click function

.wrapper-noaction { position: absolute; margin-top: -558px; width: 100%; height: 100%; border: 1px solid red; } .video-stat { width: 94%; margin: 0 auto; } .player-control { background: rgba(0, 0, 0, 0.8); border: 1px ...

Using preventDefault in the compositionend event does not make any difference

var inputNode = document.getElementById('view_1'); inputNode.addEventListener('compositionend', function(e) { console.log(e.cancelable); // true e.preventDefault(); }); <div id="view_1" class="view" contenteditable="true> &l ...

What is the sequence of the middlewares for error handling and handling of 404 errors?

The express.js website has confused me with contradictory statements regarding error-handling middleware. According to one page, you should define error-handling middleware last, after other app.use() and routes calls. However, another page states that you ...

What is the purpose of uploading the TypeScript declaration file to DefinitelyTyped for a JavaScript library?

After releasing two JavaScript libraries on npm, users have requested TypeScript type definitions for both. Despite not using TypeScript myself and having no plans to rewrite the libraries in TypeScript, I am interested in adding the type definition files ...

Are `<text>` nodes unable to utilize ligature fonts in CSS/SVG?

Check out this JsFiddle demo: http://jsfiddle.net/d0t3yggb/ <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <div class="material-icons">add add add add</div> <svg width="100%" height="100% ...

Passing JSON information through PatternLab

Incorporating an atomic pattern and passing data from a JSON array is my goal. Below are the code snippets and JSON file. anchor-link.mustache <a href="{{ url }}" class="{{ class }}">{{ label }}</a> footer-nav.mustache <ul class="menu ve ...

NPM packages: Providing a comprehensive assets and images delivery solution package

After creating a custom (angular2) npm package and uploading it to my personal registry, I encountered an issue with delivering the icons along with the component. The component should display an icon by using the following template: <span [class]="& ...

My code fails to recognize the top property when the window size is 1300px

Error at the Top Not Being Recognized: Hello, I am facing an issue where the top part of the webpage does not behave correctly when the window size is less than 1300px. The condition set for 100% top only applies after refreshing the page; otherwise, it d ...

NextJS application failing to display SVG icon in the absence of internet connection

https://i.stack.imgur.com/M9reE.jpg https://i.stack.imgur.com/Yyg4g.jpg Upon inspection of the provided images, it is evident that the src URL points to a location within the nextjs public folder. The issue arises when there is no internet connection - i ...

Initiate a POST ajax request to retrieve the file.Let's

I'm currently working on an Asp.Net MVC project and I have a piece of code in my View that looks like this: $.ajax({ beforeSend: function () { LoadStart(); }, complete: function () { LoadStop(); ...

Having trouble understanding why ng-resource refuses to return an array

I've recently encountered an issue while using AngularJS and NGResource. For some reason, every time I try to use the query function, I receive an empty array in return. Within my controller, the code looks like this: Task = $resource('/tasks&a ...

The bundle.js file is displaying HTML code instead of JavaScript

I have been working on setting up redux server-side rendering using express.js. Most of the setup is done, but I encountered an error while trying to render the page in the browser. The error message Uncaught SyntaxError: Unexpected token < is appearin ...

Customize Button Colors in Bootstrap 4

I'm encountering difficulties when attempting to change the color of the buttons labeled "Print," "Excel," and "PDF". Despite referring to a guide, I wasn't able to succeed. The provided test case differs from my code but shares the same CSS and ...

Steps for integrating a valid SSL certificate into a Reactjs application

After completing my ReactJS app for my website, I am now ready to launch it in production mode. The only hurdle I face is getting it to work under https mode. This app was developed using create-react-app in a local environment and has since been deployed ...

how can I enable pass-through functionality in express middleware?

Currently, I have a POST API endpoint named /users which is used to retrieve the list of users. The reason behind using POST instead of GET is because the request body can be quite large and it may not fit in the URL for a GET request. In this scenario, i ...

Encountering excessive re-renders while using MUI and styled components

Hey there! I recently worked on a project where I used MUI (Material-UI) and styled-components to render a webpage. To ensure responsiveness, I made use of the useTheme and useMediaQuery hooks in my web application. My goal was to adjust the font size for ...