Getting the output from AJAX when the onreadystatechange event occurs

Struggling with retrieving a value from a function and storing it in a variable? Getting an "undefined" result due to JavaScript's asynchronous nature? Unsure how to fix this using "callbacks" or "promises"? Check out the code snippet below. The goal is to extract the exchange rate stored in "value" variable and assign it to the "rate" variable for further use in the code.

var rate = rateCalc();
var currency = "EUR";

function rateCalc(){
var value;
if (currency != "EUR"){
var xmlhttp = new XMLHttpRequest();
var rateURL = "http://query.yahooapis.com/v1/public/yql?q=select%20rate%2Cname%20from%20csv%20where%20url%3D'http%3A%2F%2Fdownload.finance.yahoo.com%2Fd%2Fquotes%3Fs%3D"+"EUR"+"HKD"+"%253DX%26f%3Dl1n'%20and%20columns%3D'rate%2Cname'&format=json";
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var json = JSON.parse(xmlhttp.responseText);
value = json.query.results.row.rate;
alert("At this position the value is defined: "+ value);
return value;
}
}
xmlhttp.open("GET", rateURL, true);
xmlhttp.send();
}

else {
value = 1;
return value;
}
}
alert("The return statement somehow didn't work: "+ rate);

If this question has been answered before, apologies, as I'm new here.

Thanks, René

Answer №1

In JavaScript, you cannot directly return anything from an async function. Instead, you need to create a new function and use it as a callback function. Here is an example demonstrating this concept:

    var rate = rateCalc();
    var currency = "EUR";

    function rateCalc(){
        var value;
        if (currency != "EUR")  {
            var xmlhttp = new XMLHttpRequest();
            var rateURL = "http://query.yahooapis.com/v1/public/yql?q=select%20rate%2Cname%20from%20csv%20where%20url%3D'http%3A%2F%2Fdownload.finance.yahoo.com%2Fd%2Fquotes%3Fs%3D"+"EUR"+"HKD"+
                              "%253DX%26f%3Dl1n'%20and%20columns%3D'rate%2Cname'&format=json";
            xmlhttp.onreadystatechange = function() {
                if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                    var json = JSON.parse(xmlhttp.responseText);
                    value = json.query.results.row.rate;
                    alert("At this position the value is defined: "+ value);
                    valueCallBack(value); //Callback function

                }
            }
        xmlhttp.open("GET", rateURL, true);
        xmlhttp.send();
        }

        else {
            value = 1;
            return value;
        }
    }

   function valueCallBack(value){
     console.log("value is " + value);      
   } 

Update : Alternatively, you can utilize the Promise API introduced in ES6 or leverage JQUERY deferred objects for handling asynchronous operations.

Answer №2

Make sure not to leave xmlhttp.send() empty. Give this a try - it should work!

xmlhttp.send(null);

Answer №3

If you want to ensure that the value is displayed properly without any undefined issues, you can pass it to another function.

Give this a try:

fetchExchangeRate();
var currency = "EUR";

function fetchExchangeRate() {
    var value;

    if (currency != "EUR")  {
        var xmlhttp = new XMLHttpRequest();
        var rateURL = "http://query.yahooapis.com/v1/public/yql?q=select%20rate%2Cname%20from%20csv%20where%20url%3D'http%3A%2F%2Fdownload.finance.yahoo.com%2Fd%2Fquotes%3Fs%3D"+"EUR"+"HKD"+"%253DX%26f%3Dl1n'%20and%20columns%3D'rate%2Cname'&format=json";

        xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                var json = JSON.parse(xmlhttp.responseText);
                value = json.query.results.row.rate;
                displayValue(value);
            }
        };

        xmlhttp.open("GET", rateURL, true);
        xmlhttp.send();
    } else {
        value = 1;
        displayValue(value);
    }
}

function displayValue(rate) {
    alert("Value: "+ rate);
}

Answer №4

Here is the revised code implementation. The callback function is now utilized for subsequent calculations with the returned value. Special thanks to @Jijo John and @nx0side for their assistance.

let currency = "HKD";
let value;

if (currency !== "EUR") {
    let xmlhttp = new XMLHttpRequest();
    let rateURL = `http://query.yahooapis.com/v1/public/yql?q=select%20rate%2Cname%20from%20csv%20where%20url%3D'http%3A%2F%2Fdownload.finance.yahoo.com%2Fd%2Fquotes%3Fs%3D${"EUR"}${"HKD"}%253DX%26f%3Dl1n'%20and%20columns%3D'rate%2Cname'&format=json`;
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            let json = JSON.parse(xmlhttp.responseText);
            value = json.query.results.row.rate;
            valueCallBack(value); //Callback function
        }
    };
    xmlhttp.open("GET", rateURL, true);
    xmlhttp.send();
} else {
    valueCallBack(1);
}

// All further calculations with "value" should be performed within this function.
function valueCallBack(value) {
    // Example calculation
    let result = 70000 / value;
    console.log("Result is " + result);
}

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 there a way for me to receive numerical values instead of NaN?

I'm currently facing a challenge in creating a Fibonacci number generator and I've hit a roadblock. It seems like I have a solution, but the appearance of NaN's is causing me some trouble. function fibonacciGenerator (n) { var output = [ ...

Rows per page options fail to display in the DataTable component

I need to display a dropdown selector for rows per page in the DataTable component from PrimeVUE. This is the sample HTML code I currently have for the DataTable: <DataTable :value="comunicaciones" :paginator="true" :rows="numFilas" :rowsPerPageOption ...

Is there a way to update a variable in a controller using AJAX?

Is it possible to update a variable in the controller using Ajax? Controller: $basl = array(2018,11,18,0,0); $deger = 3; $baslamatarihi=Carbon::create($basl[0],$basl[1],$basl[2],$basl[3],$basl[4]); $bitistarihi = Carbon::create($basl[0],$basl[1],$basl[2] ...

How can we convert milliseconds to the corresponding date and time zone in Java?

1)I am trying to determine the user's timezone and current time using the following code snippets: Calendar currentdate1 = Calendar.getInstance(); TimeZone tz = Calendar.getInstance().getTimeZone(); System.out.println("time zone"+tz); System.out.pri ...

Sending blank information via Ajax request

I've been attempting to perform an AJAX post to my Express API. My expectation was to receive {user:Todd} in the data object, but whenever I attempt to log the request body, it appears empty. $.ajax({ url: '/api/test', type: 'POST ...

Discover information based on attribute value with MarkLogic

I am working on a MarkLogic 8 database and I have the following code snippet: declareUpdate(); var book0 = { id: fn.generateId({qwe: 'book'}), username: 'book', password: 'pass' }; var book1 = { id: fn.generateId({asd ...

Is it possible to incorporate custom scripts into the <head> section of the index.html file in Docusaurus?

I decided to organize my code by creating a scripts folder within the static directory. Inside this folder, I added a custom JavaScript file named "GetLocation.js". The path to this file is project/website/static/scripts/GetLocation.js Upon looking into s ...

Modify File Name with Fine Uploader: Personalize Your File Titles

When attempting to save files with a specific directory structure in my S3 bucket, I am encountering an issue where the getName method only returns the reference instead of the actual value of the file name. The output of getName is displayed as [object O ...

What is the best way to incorporate a third-party element into Vue using a script tag?

I am in the process of developing a website and I would like to include a widget that links to a podcast on BuzzSprout. Initially, I created the site using HTML to test out different designs, but now I am looking to transition it to VueJS. In my HTML vers ...

Is there a way to prevent duplicate requests in jQuery?

I'm new to using jquery. Can someone please assist me with solving my current task? Here is the code that I have for a form with a select element. It triggers on the onfocus event: function sendBall(id){ $('#bal_'+id).blur(function(){ $.aj ...

a tutorial on linking component data to a prop value

Is there a way to connect the searchString value in my Vue component to the item value in the html template it uses? I need to pass this value to the method called in my Ajax request. Vue: Vue.component('user-container-component', { props: ...

Utilizing the power of Vue.js version 2.x alongside the sleek features of Bootstrap

I'm currently experimenting with incorporating Bootstrap 5 into Vue (2.x) without relying on any third-party libraries. My approach involves creating a custom wrapper for select Bootstrap components that I intend to utilize. For guidance, I've b ...

Unexpected restarts are occurring in a lengthy PHP script

I have a PHP script that I execute using the $.ajax() Javascript function: $.ajax({ type: "POST", url: "/myscript.php", data: $("#my-form").serialize() }); Details of myscript.php class myclass{ public function __construct(){ $i ...

Authenticating Users with Laravel and Vue.js

In my Vue.js application, I have implemented a login system. The main script in my main.js file includes the necessary imports and configurations: import Vue from 'vue'; import NProgress from 'nprogress'; import Resource from 'vue ...

Strategies for making a child div fade out when the parent div is hovered over

I have a div with the class name ordershape and inside it, there is another div called fad-res. My goal is to display the corresponding fad-res when I hover over a specific ordershape, while hiding the other divs. <div class="ordershape"> & ...

Is it possible to safeguard undisclosed data in browser console?

Can JavaScript be employed to prevent users from editing hidden fields through the browser console? ...

Issue encountered when attempting to develop a countdown timer using Typescript

I am currently working on a countdown timer using Typescript that includes setting an alarm. I have managed to receive input from the time attribute, converted it using .getTime(), subtracted the current .getTime(), and displayed the result in the consol ...

AngularJS encounters an error message stating, "The data being posted is invalid in syntax according to the client."

Angular post request $http({ method: 'POST', url: '/DineOut/send', contentType:'application/json', dataType:'json&ap ...

Registering the service worker resulted in an error stating "Undefined is not a function"

When attempting to register a service worker using default React code, I discovered that some users were encountering a `TypeError: undefined is not a function` on the line `.then(registration => {` inside the registerValidSW function. Although it works ...

Create a Boxplot chart using Chart.js that dynamically adjusts the minimum and maximum values to allow for additional space on either

I am utilizing chartjs v2.9 for creating a boxplot and my code structure is as follows: function generateRandomValues(count, minimum, maximum) { const difference = maximum - minimum; return Array.from({length: count}).map(() => Math.random() * ...