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

The Resharper guideline "Function Parameter" doesn't allow the usage of AngularJS service names

I have a question regarding naming conventions in my AngularJS app. Currently, all my service names start with an uppercase character. However, I am facing an issue where service parameters must match the service name, but Resharper's JavaScript "Func ...

Is it possible for asynchronous functions to write to the same object concurrently and result in invalid values?

I have been experimenting with the code below to see if it can cause any issues with the integer i in the object context. My tests so far have not revealed any problems. // Node.js (v10.19.0) const Promise = require('promise') // object access ...

What is the best way to extract and count specific values from a JSON file using JavaScript?

My JSON data looks like this: /api/v1/volumes: [ { "id": "vol1", "status": "UP", "sto": "sto1", "statusTime": 1558525963000, "resources": { "disk": 20000000 }, "used_resources": { "disk": 15000000 }, "las ...

Tips for managing various potential return types in TypeScript?

In my research on the topic, I came across a discussion thread about obtaining the local IP address in Node.js at Get local IP address in Node.js. In that thread, there is a code snippet that I would like to incorporate: import net from 'net'; c ...

Ways to retrieve and update the state of a reactjs component

I'm facing an issue with modifying a React JS component attribute using an event handler. export default interface WordInputProps { onWordChange:(word:string) => void firstLetter:string disabled?:boolean } These are the props for my co ...

The validation feature in 1000hz Bootstrap seems to be malfunctioning

I've been working on implementing validation using the 1000hz bootstrap validation plugin. Most things are going smoothly, but I'm encountering two issues: 1). The data-match attribute doesn't seem to be working even when I enter the same p ...

Issues arising with utilizing Github for hosting Angular applications

After developing a site with Angular, everything was running smoothly on my local host. However, when I decided to host the site on GitHub, two errors appeared. You can access my site through this link: Here is a screenshot of the errors encountered [1]: ...

Submitting Data Forms with AJAX on dynamically loaded webpages

Issue with Form Submission in Ajax-Generated Page I am experiencing an issue with form submission on a page generated within AJAX. The page contains two forms, #form1 and #form2. The jQuery code for submitting the form is as shown below: jQuery("#form1" ...

Tips for Sending <Div> Data to a Servlet

I attempted to pass the content of an entire div in a form action URL using JavaScript. However, when I try to retrieve this request parameter as a String on the servlet side, it is returning [object Object]. Below is my code for the form and JavaScript: ...

Tips for implementing a JavaScript Material Design framework in ReScript code?

I am attempting to integrate the material-ui library into a Rescript/React application. The code snippet below demonstrates how to display a button: @module("@material-ui/core/Button") external button: string = "default" @react.compone ...

Identifying mismatches in data mapping

I'm currently working on combining multiple observables into a single observable using RXJS and the CombineLatest operator. Initially, my code was functioning correctly with 6 observables, but upon adding 5 more, the compiler started encountering issu ...

The error message "Property 'pipe' is not found on 'ReadableStream<Uint8Array>'" indicates that the pipe method cannot be used on the given type

Within a function resembling Express.js in Next.js, I am working on fetching a CSV file with a URL that ends in .csv. Using the csv-parser library to stream the data without persisting the file and transform it into an array. Here is an excerpt of the code ...

The hit detection algorithm seems to be malfunctioning, and the reason behind it is unclear. (Using Javascript/Processing

I am a beginner in game programming and programming in general. In the past, I have created a clone of "Flappy Bird" and some other games using the hit detection algorithm from the Mozilla Developer Network here. Currently, I am facing an issue while tryi ...

What leads to the occurrence of the "maximum call stack size exceeded" error?

I am currently developing a Vue 3 and Bootstrap 5 application. To integrate a date-picker functionality, I opted for the Vue 3 Datepicker plugin available at Vue 3 Datepicker. Within the file components\Ui\Datepicker.vue, I have included the fol ...

Steps for creating a click event for text within an Ag-Grid cell

Is there a way to open a component when the user clicks on the text of a specific cell, like the Name column in this case? I've tried various Ag-Grid methods but couldn't find any that allow for a cell text click event. I know there is a method f ...

Determine the data type of an object's key

I have a XInterface defined as: export interface XInterface { foo: (() => Foo[]) | Foo[], bar: string, baz: number } When declaring an object using this interface, I want the type of foo to be Foo[], like so: const myObj: XInterface = { ...

Viewing an image from a local file on a web browser

I am currently working on a project where I want the user to be able to select a local image that will then be displayed on the page. As someone who is new to web development, I did a lot of research and found some helpful information on StackOverflow. I t ...

Utilizing ES6 Functions to Transform Objects into Arrays

Is there a way to convert a JavaScript object into an array using ECMAScript-6? Take, for instance: var inputObj = {a:'foo', b:[1,2,3], c:null, z:55}; The desired outcome would look like this: ['foo', [1,2,3], null, 55] The seque ...

Is it possible to retrieve all mandatory attributes of a TypeScript object?

Is there a method or approach available that can retrieve all necessary properties from a TypeScript interface or an object? For instance, something along the lines of Object.getOwnPropertyDescriptors(myObject) or keyof T, but with the specific details o ...

Similar to the "beforesend" functionality in JavaScript, there is a corresponding feature

When attempting to post a comment in my ionic app using the Wordpress api, I encountered error 401 (unauthorized) indicating that the Wordpress api does not recognize me as logged in. This is the code I am using: postComment(params?: any) { let nonce = l ...