Ensure that all asynchronous code within the class constructor finishes executing before any class methods are invoked

Looking to create a class that takes a filename as a parameter in the constructor, loads the file using XmlHttpRequest, and stores the result in a class variable. The problem arises with the asynchronous nature of request.onreadystatechange, causing the getData method to be called before the constructor finishes executing. This leads to an undefined data result. How can I ensure that the methods in this class wait for the file to finish loading before proceeding? Since I'm relatively new to async code and promises, please explain it to me like I'm 5 years old.

The current workaround in my code involves wrapping the method in a timeout, which somewhat addresses the issue. However, utilizing the synchronous version of request.open is not recommended due to performance concerns. So, that option is off the table as well.

test.html

<html>
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <script src="test.js"></script>
        <script>
            let test = new testClass('test.json')
            console.log(test.getData)
        </script>
    </body>
</html>

test.js

class testClass {
    constructor(filename) {
        this.loaded_data = undefined

        let request = new XMLHttpRequest()

        request.overrideMimeType('application/json')
        request.open('GET', filename)
        request.onreadystatechange = () => {
            if (request.status == '200' && request.readyState == 4) {
                /* Load and parse JSON here */
                this.loaded_data = 'foo'
            }
        }

        request.send()
    }

    get getData() {
        setTimeout(() => {
            console.log(this.loaded_data)
        }, 500);

        return this.loaded_data
    }
}

Answer №1

Looking at the design aspect, the File itself is not considered "asynchronous", but rather the process of loading that file involves asynchronous behavior. It is important for your class to only represent a file that has already been loaded:

 class File {
    constructor(data) { this.data = data; }

To load a file asynchronously, you can create a static method within the class:

 static async load(filePath) {
      let response = await fetch(filePath);
      let jsonData = await response.json();
      return new File(jsonData);
   }
 }

You can then utilize this method as follows:

(async function() {
   let myFile = await File.load('example.json');
   console.log(myFile.data);
 })()

Note: The fetch() function is preferred over XmlHttpRequest due to its Promise-based nature, compatibility with async / await, and convenience in handling responses. In this case, the response is parsed as JSON.

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

Load images in advance using jQuery to ensure they are cached and retrieve their original sizes before other activities can proceed

When a user clicks on a thumbnail, I aim to display the full-size image in a div. To achieve this, I want to determine the original size of the image based on its source URL before it loads, allowing me to set the appropriate dimensions for the container. ...

AngularJS: Pause the data binding functionality temporarily

How can I temporarily deactivate data binding in AngularJS? I am working with a list called items that is being displayed using ng-repeat. I need to perform some operations on this list without immediately updating the page, as this could cause slowdown. ...

Generate an li element that is interactive, containing both text and a span element

I am dealing with a JSON array that looks like this: var teamDetails=[ { "pType" : "Search Engines", "count" : 5}, { "pType" : "Content Server", "count" : 1}, { "pType" : "Search Engines", "count" : 1}, { "pType" : "Business", "count" : 1,}, { "pTyp ...

Efficient method of delivering cohesive information from database to user without the need for continuous querying

Within the database, there is stored data about each user that typically remains constant. However, occasionally a user may update their information, such as changing their name. This data includes the user's name, username, and company details. The ...

What is the best way to make an element fixed vertically in a mobile browser while also enabling horizontal scrolling?

When using a Desktop browser, I have found a javascript code that allows me to vertically fix an element while still enabling horizontal scrolling. The element is repositioned with each scroll event. You can test this out by trying both horizontal and vert ...

Tips for transferring a dataTable from C# code behind to jQuery

I am trying to pass a string as a table of data from C# code behind to jQuery using two functions: C# [System.Web.Services.WebMethod(EnableSession = true)] public static List<ListItem> GetImageArray(string AccNo) { string result = string.Empty; ...

Obtain the rotated coordinates for the top and left positions

I am trying to determine the rotation of a specific point in terms of its top and left positions. It's proving to be quite complex as it involves knowing the original top and left coordinates, applying scaling, and then calculating the rotation. Curr ...

transferring a value from php to javascript using a form's id

I'm facing an issue where I need to pass a dynamically generated ID from a form to JavaScript. <script type="text/javascript"> $(function() { $(".button-call").click(function() { var fld = "<?= $div_id;?>"; var test = $(fld).val ...

Implement a function that attaches an event listener to generate a new table row dynamically

I am currently facing an issue with my table that has ajax call functionality to add rows within the tbody element. The table is already set up on the html page. <table id='mytable'> <thead> <tr> <th>First Col</th> & ...

Express API encounters an issue with multer and body-parser as req.file is undefined

I am in the process of developing an API that will need to handle file uploads along with other GET and POST requests. To manage file uploads, I am using 'multer' while utilizing 'body-parser' for all other HTTP requests. My goal is to ...

Discovering ways to showcase JSON response in JavaScript or PHP

Currently, I am integrating the Coin Warz API into my website. The API sends responses in JSON format. I have attempted to display this data in a table format using PHP, but unfortunately, I am encountering difficulties. The JSON Response is as follows: [ ...

The length of the notification is determined by the ReadFlag

JS: function fetchNotifications(){ $.ajax({ url: "getgroupednotification.json", type: "GET", crossDomain: true, success:function(response){ ...

Redirecting with Express js when the cookie is not found

I successfully integrated Facebook login using Passport-js and also set up Cookie-strategy for traditional username/password login on my Express-js backend with a React front-end. The backend and frontend are hosted on separate servers and domains (backend ...

The transformation rotation applied in CSS must not have any impact on the styling of my span and paragraph

Snippet: .details-section{ background-color: rgb(83, 83, 83); height: 200px; } .icon-container{ border: 2px solid #c49b63; width: 90px; height: 90px; transition: 0.5s ease; } .box i{ font-size: 60px; color: black; margin-top: 13px ...

Pressing the ENTER key does not submit the text box data in Rails/Bootstrap, but clicking the SUBMIT button does

I need assistance with my Rails 4 and Bootstrap 3 project. I have implemented an email address field on my page (localhost:3000) where users can enter their email and click the SUBMIT button to send it to the MongoDB database. However, pressing the ENTER k ...

Including content without triggering the digest cycle (utilizing raw HTML) within a Directive

My goal is to include raw HTML inside a directive for later transclusion (to populate a modal when opened). The issue arises when the contents of dialog-body are executed, triggering the ng-repeat loop and causing the template to be rerun, leading to a po ...

Diverse behaviors exhibited by an array of promises

I've developed a function that generates an array of promises: async addDefect(payload) { this.newDefect.setNote(payload.note); this.newDefect.setPriority(payload.priority); const name = await this.storage.get(StorageKeys.NAME); ...

Executing a Vue method from the main.js file within a Vue.js document

Why can't I call my method in App.vue? Shouldn't the div with id='App' in the App file allow me to access methods within it? Main.js new Vue({ render: h => h(App), methods:{ gesamt:function () { return 'Hello&a ...

Guide to configuring Ionic Auto Height Sheet modal in Vue 3

Trying to implement an Ionic Auto Height Sheet modal in a Vue 3 project (https://ionicframework.com/docs/api/modal#auto-height-sheet). Below is the code I have written. In ion-tab-button #3, I included id="open-modal". Underneath the ion-tab-but ...

Guidelines for combining inner objects with their parent in Javascript

I need assistance with using the filter function in Angular.js because it's not working on objects. Is there a way to merge a nested object into its parent using Javascript? For example, I have the following data structure: { "data" : [ { "ch ...