javascript problem with class method for loading json file

I've encountered an issue with my class setup below. Despite most things working, the console keeps throwing an error when json.onload is triggered. The error message reads "

Uncaught TypeError: Cannot read property of 'push' of undefined
".

How can I resolve this error?

var Clazz = new function(){
  this.library = [];

  this.add_library = function(file){
    var json = new XMLHttpRequest();
    json.overrideMimeType("application/json");
    json.open("GET", file, false); //needs to be synchronise
    json.onload = function(){
      this.library.push(JSON.parse(json.responseText));
      do something...
    };
    json.send(null);
  };
}

Clazz.add_library("path/file.json");

Solution

Simply change this.library.push(...); to Clazz.library.push(...);

Answer №1

The reason for this behavior is the change in scope within the function this.add_library

var Class = new function(){
  this.library = [];
    var self = this;

  this.add_library = function(file){
    var json = new XMLHttpRequest();
    json.overrideMimeType("application/json");
    json.open("GET", file, false); //needs to be synchronise

    json.onload = function(){
        console.log(self)
      self.library.push(JSON.parse(json.responseText));
      //do something...
    };
    json.send(null);
  };
}

new Class.add_library("path/file.json");

Answer №2

Experiment with this code snippet:

var MyClass = new function(){
  this.collection = [];

  this.add_item = (item) => {
    var data = new XMLHttpRequest();
    data.overrideMimeType("application/json");
    data.open("GET", item, false); //must be synchronized
    data.onload = () => {
      this.collection.push(JSON.parse(data.responseText));
      // do something...
    };
    data.send(null);
  };
}

Alternatively, you could try using the .bind(this) method to address the issue with the visibility of this within the function's scope.

Answer №3

The issue at hand revolves around the concept of context in JavaScript. JavaScript has different scenarios for the this keyword, and your example involves two of them:

  1. Method invocation - this refers to the object calling the method.
  2. Function invocation - this points to the global object or undefined in strict mode.

Let's take a closer look at your code (I will make some adjustments for clarity):

var Clazz = {
    library: [], 

    add_library: function(file){ 
        // When using `this.library` here, it refers to the `library` property of the Clazz object
        // and it works fine since `this` points to the Clazz object
        json.onload = function(){
            this.library.push(JSON.parse(json.responseText));
            // However, in this section `this` refers to the global object
            // because `json.onload` is a function, even though it is within the `add_library` method
        };
    };
}

So, how can we solve this issue? Here are a few suggestions:

  1. Utilize .bind():

    json.onload = function(){
        this.library.push(JSON.parse(json.responseText));
    }.bind(Clazz);
    
  2. Assign the context to a variable:

    const self = this;
    json.onload = function(){
        self.library.push(JSON.parse(json.responseText));
    }
    
  3. Use arrow function:

    json.onload = () => {
        this.library.push(JSON.parse(json.responseText));
    }
    

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

How can I asynchronously parse JSON data from a URL on a Windows phone and display it in a

As an Android developer exploring the world of Windows Phone for the first time, I came across this resource on how to handle list boxes in Windows Phone 7/8. However, my challenge now is parsing JSON from a URL instead of XML as shown in the example. Whil ...

Ways to verify the presence of an element in a list

I found this interesting JS code snippet: ;(function ($) { $('.filter-opts .opt').click(function(){ var selectedName = $(this).html(); $('.append').append('<li>' + selectedName + '</li> ...

Adding parameters to a URL is a common practice

"Adding additional information to a URL that was previously included?" I apologize for the confusing title, but I can't find a better way to phrase it. Perhaps an example will make things clearer. Let's say I have URL 1: http://example.com/?v ...

Using vue.js to customize the items shown in the ox carousel

https://i.sstatic.net/yTONv.jpg Greetings, I am currently utilizing the "carousel" component from Buefy with Vue.js. In desktop resolution, I need to display 3 elements, but on mobile devices, I want only one article to be visible. I have created a functi ...

Laravel Eloquent model, text being cut off at maximum length

While working with Laravel, I encountered an issue when loading a database row into an Eloquent object. The problem arose from one of the columns being a longtext type containing a JSON encoded array with over 2 million characters. The original error I fac ...

Is it possible to create a struct that automatically transforms from serde_json::Value using Deserialize?

When it comes to deserializing from a string directly into a struct, everything works flawlessly. However, there are instances where you might already have a serde_json::Value and wish to convert it into a struct. For example, imagine you need to load a R ...

Unable to trigger jQuery onclick event on nested div elements

I'm experiencing an issue with my web-page where two buttons at the top are not responding to a sorting function on the nested #byFilter. Despite trying to apply the onclick(function()) method, it doesn't seem to work. Javascript $(document).re ...

Is there a way to invoke a different function within a class from a callback function in an HTTP request?

Having an issue with my HTTP GET request function in the "CheckPrice" class. When trying to call another function within the class callback, it's showing as undefined. Any suggestions? const got = require("got") class PriceCheck { constructor() { ...

Why isn't httpUploadProgress functioning correctly with Buffer data?

Recently, I have ventured into the world of node.js/express as I am attempting to create a multiple image uploading application utilizing cloudfront and an s3 bucket. My goal is to display a progress bar for the user by integrating socket.io for real-time ...

Fetching Data from Response Headers in Angular 4.3.3 HttpClient

(Text Editor: Visual Studio Code; TypeScript Version: 2.2.1) The main objective here is to fetch the headers of the response from a request Let's consider a scenario where we make a POST request using HttpClient within a service: import { Injec ...

Combining several objects into a one-dimensional array

I am encountering a small issue with correctly passing the data. My form is coming in the format {comment:'this is my comment'} and the id is coming as a number. I need to send this data to the backend. let arr = []; let obj = {}; o ...

Listening for changes in class property values in TypeScript with Angular involves using the `ngOnChanges`

Back in the days of AngularJS, we could easily listen for variable changes using $watch, $digest... but with the newer versions like Angular 5 and 6, this feature is no longer available. In the current version of Angular, handling variable changes has bec ...

Is there a way to invoke a method in Jest Enzyme without using .simulate()?

During my unit testing for a React flight seat selection application using Jest/Enzyme, I encountered a scenario where I need to test a method within my class-based component that runs after a button is clicked. However, the button in question resides deep ...

Retrieve the function-level variable within the while loop's else statement

Struggling with node.js, I find myself facing the challenge of accessing a variable declared at the start of a function from an else statement nested within a do while loop: function myFunction(){ var limit = 2000; var count; var total; va ...

To validate any object, ensure that it contains a specific key before retrieving the corresponding value in typescript

When looking at a random object, my goal is to verify that it follows a certain structure. obj = {WHERE:{antherObject},OPTIONS{anotherObject}} Once I confirm the object has the key using hasProperty(key), how can I retrieve the value of the key? I thoug ...

Select state and city options similar to the national breakdown page

I'm attempting to replicate a state and city selection box similar to the one on the NTTS Breakdown website. You can see it in action here: When you select a state on the left side of the webpage, the city selection box displays "loading data" and th ...

Node.js server experiences a crash after attempting to send a large string using res.send()

I've recently started learning JavaScript and NodeJs. I'm facing an issue with my Nodejs application crashing when a get request is made, specifically when trying to return a large string. app.mjs app.get('/log', function (req, res) { ...

Top method for verifying email existence in ASP.NET database

In our current asp.net web application, we are facing some challenges with using the update panel on the user registration page to check for existing users. These issues include: 1- The update panel tends to slow down the process. 2- The focus is lost wh ...

ReactJS presents an issue where buttons on the navigation bar are not properly aligned

I am currently utilizing the navbar component from Bootstrap 5, and I've encountered a UI problem. What is my current setup? This is the existing structure of my navbar: https://i.sstatic.net/eETzd.png What is my desired outcome? I aim to have the n ...

Restricting the Zoom Functionality in a Web-Based Project on a Touch-Enabled Display

I am currently working on a project that is web-based and runs on localhost. I need to prevent users from zooming in on the user interface. Is there a way to accomplish this using JavaScript? And can I achieve this restriction specifically on Google Chrome ...