Use GM.xmlHttpRequest response outside of the request

Hi,

I just want to fetch currency exchange rates from an api returning JSON data. It works, but I can't use the value outside of the function.

// ==UserScript==
// @name         fetch currency exchange rate
// @namespace    graphen
// @version      1.0.0
// @author       Graphen
// @match        *example.com*
// @grant        GM.xmlHttpRequest
// @noframes
// ==/UserScript==

/* jshint esversion: 6 */
(function (doc) {
    'use strict';

    var ER, res;
    function fetchExchangeRate(erUrl) {
        GM.xmlHttpRequest ({
            method :  'GET',
            url:      erUrl,
            headers : { 'Content-type' : 'application/json' },
            onload :  function(xhr) {
                res = JSON.parse(xhr.responseText);
                //console.log("Got exchangerate USD --> EUR from server api.exchangeratesapi.io :");
                //console.log(res.rates.EUR); // THIS WORKS
                ER = res.rates.EUR;           // THIS DOESNT WORK (undefined outside)
                return ER;                    // THIS DOESNT WORK (undefined outside)
                // return res.rates.EUR;      // THIS DOESNT WORK (undefined outside)
            },
            onerror : function(xhr) {
                //console.log("Error fetching JSON from xhr.");
                return false;
            }
        });
    }
    fetchExchangeRate("https://api.exchangeratesapi.io/latest?base=USD&symbols=EUR");
    //console.log(fetchExchangeRate("https://api.exchangeratesapi.io/latest?base=USD&symbols=EUR"));
    console.log(ER);

})(document);

No matter if I make a copy to a variable or make a direct return - it always says "undefined" outside of the function.

Viestejä yhteensä

  • editoi May 15 [?]

    You can't use it outside of the function. The data is fetched asynchronously - GM.xmlHttpRequest basically registers a one-time event listener for "onload" event, immediately exits, then the rest of your code runs, then the data is fetched and the callback is invoked - which happens at some point in the future.

    You can wrap GM.xmlHttpRequest into a Promise and switch to async/await syntax, look for tutorials and existing libraries here on GF.

  • Thanks for the good explanation, which now requires a not-so-pleasant solution from me :smile:

  • Simply put all the processing of data within onload function

  • @trespassersW Already thought about that but it's kind of ugly. To make sure the code runs I may have to duplicate all the stuff to do into onerror?
    I already started to learn about that asynchronous promise-resolve stuff, but it's not easy as beginner. First I wanted to get comfortable with objects, anonymous functions, callbacks, arrow style notation, ...

  • duplicate all the stuff to do into onerror?

    You may write a separate function for "duplicated stuff" and use in both event handlers

  • Ah right, I can get stuff "from outside in", apparently just not from inside out of the xmlHttpRequest.

Kirjaudu sisään tai Rekisteröidy kommentoidaksesi.