Error: The method 'getAjaxResponse' is not available for Object #<AbstractAjaxReq>

Looking to incorporate OOP best practices into my javascript code. Currently, I have an abstractAjaxRequest with child classes defining the getAjaxResponse function. However, I am encountering an error on the line self.getAjaxResponse(). Any ideas on how to resolve this issue?

function soapReq() {
    var ajaxRequest = new SignInAjaxReq();
    ajaxRequest.init();
    var SOAPRequest = getSOAPHead();
    var bodyArgs = getLoginAttempt();
    SOAPRequest += getSOAPBody(bodyArgs[0], bodyArgs[1], bodyArgs[2]);
    SOAPRequest += getSOAPFoot();

    var url = 'xxx'
    ajaxRequest.ajaxRequest.open('POST', url, true);
    ajaxRequest.ajaxRequest.setRequestHeader( "Content-Type","text/xml; charset=utf-8");
    ajaxRequest.ajaxRequest.send(SOAPRequest);
}    

function AbstractAjaxReq() {
    var self = this;
    this.init = function() {
        self.ajaxRequest = new XMLHttpRequest();
        self.ajaxRequest.onreadystatechange = function() {
            if(self.ajaxRequest.readyState === 4){
                self.getAjaxResponse() // error here
            }
        };
        return self.ajaxRequest;
    };
};

function SignInAjaxReq() {
    var self = this;
    this.getAjaxResponse = function() {
        var xml = self.ajaxRequest.responseXML;
        var x=xml.getElementsByTagName("signInResult");
        for (i=0;i<x.length;i++) { 
            console.log(x[i].childNodes[0].nodeValue);
        }
    };
};
SignInAjaxReq.prototype = new AbstractAjaxReq();

Uncaught TypeError: Object #<AbstractAjaxReq> has no method 'getAjaxResponse' SoapRequest.js:42
    self.ajaxRequest.onreadystatechange

Answer №1

Your inheritance structure needs to be adjusted. When you instantiate the prototype using new AbstractReq(), the self closure variable will refer to the prototype object - which does not include a getAjaxResponse method.

Solution #1: Implement correct inheritance:

function AbstractAjaxReq() {
    var self = this;
    this.init = function() {
        self.ajaxRequest = new XMLHttpRequest();
        self.ajaxRequest.onreadystatechange = function() {
            if(self.ajaxRequest.readyState === 4){
                self.getAjaxResponse() // no more error here
            }
        };
        return self.ajaxRequest;
    };
};

function SignInAjaxReq() {
    AbstractAjaxReq.call(this); // invoke the super constructor
    var self = this;
    this.getAjaxResponse = function() {
        var xml = self.ajaxRequest.responseXML;
        var x=xml.getElementsByTagName("signInResult");
        for (i=0;i<x.length;i++) { 
            console.log(x[i].childNodes[0].nodeValue);
        }
    };
};
SignInAjaxReq.prototype = Object.create(AbstractAjaxReq.prototype);

Solution #2: Set the actual instance to self by declaring the variable in the init function:

function AbstractAjaxReq() {
    this.init = function() {
        var self = this; // declared here!
        self.ajaxRequest = new XMLHttpRequest();
        self.ajaxRequest.onreadystatechange = function() {
            if(self.ajaxRequest.readyState === 4){
                self.getAjaxResponse() // no more error here
            }
        };
        return self.ajaxRequest;
    };
};

Additionally, it is recommended to utilize the prototype! For example:

var abstractAjaxPrototype = {
    init: function() {
        var self = this; // declared here!
        this.ajaxRequest = new XMLHttpRequest();
        this.ajaxRequest.onreadystatechange = function() {
            if (self.ajaxRequest.readyState === 4){
                self.getAjaxResponse() // no more error here
            }
        };
        return this.ajaxRequest;
    }
};
function SignInAjaxReq() { }
SignInAjaxReq.prototype = Object.create(abstractAjaxPrototype);
SignInAjaxReq.prototype.getAjaxResponse = function() {
    var xml = this.ajaxRequest.responseXML;
    var x = xml.getElementsByTagName("signInResult");
    for (i=0; i<x.length; i++) { 
        console.log(x[i].childNodes[0].nodeValue);
    }
};

Lastly, avoid using init methods and instead use constructors:

function AbstractAjaxReq() {
    var self = this; // declared here!
    self.ajaxRequest = new XMLHttpRequest();
    self.ajaxRequest.onreadystatechange = function() {
        if(self.ajaxRequest.readyState === 4){
            self.getAjaxResponse() // no more error here
        }
    };
};
function SignInAjaxReq() {
    AbstractAjaxReq.call(this); // invoke the super constructor
}
SignInAjaxReq.prototype = Object.create(abstractAjaxPrototype);
SignInAjaxReq.prototype.getAjaxResponse = function() {
    var xml = this.ajaxRequest.responseXML;
    var x = xml.getElementsByTagName("signInResult");
    for (i=0; i<x.length; i++) { 
        console.log(x[i].childNodes[0].nodeValue);
    }
};

// Usage:
var ajaxRequest = new SignInAjaxReq();
// do not call ajaxRequest.init()!

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

Transform an asynchronous callback into an asynchronous generator format

I have the following function from a third-party package that I am unable to modify async function runTransaction(callback) { const client = await createClient(); try { await client.query("BEGIN"); await callback(client); } ...

Find the intersection of objects near the Raycaster in Three.js

Having trouble getting the objects that are considered 'near' the mouse using the following method: raycaster.near = 10; raycaster.far = 100; var intersects = raycaster.intersectObjects( scene.children ); if ( intersects.length > 0 ) { ...

Hide and show submenus with jQuery while ensuring that the initial submenu remains visible, along with the main menu

I am struggling to figure out how to make the first message active by default along with its corresponding menu selection in my navbar. I have implemented a show/hide functionality on the main menu click, but currently only the menu is being set as active ...

Using jQuery to insert a div class with PHP referenced

My variable stores a color name. Here is an example: <?php $myvar = blueColour; ?> I want to apply this value to the body of an html page using jQuery: <script type="text/javascript"> jQuery(body).addClass("<?php echo $myvar; ?>"); < ...

v-autocomplete no selected option

Within my Vue.js 2 and Vuetify component, I am receiving the following data : [ { "anio": 2022, "__typename": "Grupo" }, { "anio": 2020, "__typename": "Grupo" }, { "anio": 2018, "__ ...

Is there a way to speed up the processing time of parsing a 34Mb file using JSON.parse, which currently takes

Our app is currently in the development stage with a database containing approximately 4000 recipes. To save space, we have chosen to store the recipes in one locale during initial download. However, users have the option to switch locales within the app&a ...

[Vue alert]: Issue with rendering: "TypeError: Unable to access property 'replace' of an undefined value"

I'm currently working on a project similar to HackerNews and encountering the following issue: vue.esm.js?efeb:591 [Vue warn]: Error in render: "TypeError: Cannot read property 'replace' of undefined" found in ---> <Item ...

What is the best way to save the content of an RFC822 message body as a String?

let inbox = require("inbox"); let client = inbox.createConnection(false, "imap.gmail.com", { secureConnection: true, auth:{ user: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="99f4e0fcf4f8f0f5d9fef4f8f0f5b7fa ...

Is there a way to access a child component's method from the parent component using ref in Vue3?

I am encountering an issue while attempting to call the child method from the parent component in vue3 using the ref method. Unfortunately, an error is being thrown. Uncaught TypeError: addNewPaper.value?.savePaper is not a function Displayed below is m ...

Discover distinct and recurring elements

Having two sets of JSON data: vm.userListData = [{ "listId": 1, "permission": "READ" }, { "listId": 2, "permission": "WRITE" }, { "listId": 2, "permission": "READ" }, { "listId": 3, ...

Steps for generating a hierarchical menu utilizing data from a CSV file

I am looking to use a CSV file to structure the menu on my webpage. Could someone assist me in creating a nested menu using JavaScript with the provided CSV data? The columns consist of: Level, Menu name, URL 0;"Service"; 1;"Service 1";"http://some-url- ...

What is the best way to display a string state value in a React component?

I need assistance with displaying a state value that is in string format. Despite my efforts, I have not been successful in finding a solution and am feeling quite frustrated. Can anyone provide some guidance? ...

Ways to establish a default search outcome in a search box

Looking to create a search bar with JavaScript and JSON to display default search results for visitors. Currently, the search bar only shows results after text is removed. How can I show predefined search results when the page is loaded? const search = ...

The dynamic Vue.js transitions and effects are like a magic

I am using a v-for to render multiple child components: <div v-for="(pass) in scoringPass" :key="pass.decision"> <Pass :pass="pass"/> </div> Each of these child components contains a transition tag: &l ...

The unique capabilities of services and factories in Angular 1 - understanding their differences and what each excels at

After extensively combing through numerous stackoverflow posts and articles, the consensus seems to be that an angular service returns an instance, while an angular factory returns any desired object. This raises the question: what unique capabilities do ...

"Are you in search of an open source sketchpad with flash or ajax

Looking to add a drawing component to a charity website for users to create simple sketches. The component should: Allow users to draw in black on a white canvas. Save the full drawing process to the server. Save the final image to the server. Replay th ...

The lack of definition for the props value poses an issue in React.js Hooks

I'm currently developing a notepad web application that utilizes React Hooks for managing state variables. In order to fetch data from an API, I am using the axios library. The retrieved data consists of objects with fields such as _id, title, status, ...

Spinning an object using JQuery

I am currently working on a project to test my skills. I have set up a menu and now I want to customize it by rotating the icon consisting of three vertical lines by 90 degrees every time a user clicks on it. This icon is only visible on smartphones when t ...

What is the best way to create a unique custom control in Javascript, potentially utilizing jQuery?

My goal is to develop a custom control using JavaScript that includes methods, properties, and events, and can be rendered within a div element. For example, one such control could be a calendar. It would display in a div, with customizable properties for ...

Utilizing arrays for generating tables in React

I needed to design a table using data retrieved from an API, where only specific columns should be visible by default. Here are two arrays, one containing the default column headers for the table and the other containing the id and title of the data: const ...