Này người xa lạ!

Còn chờ gì nữa mà không mau đăng nhập hoặc đăng ký để cùng tham gia thảo luận với cộng đồng!

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.

Bình luận

  • đã sửa 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.

Đăng nhập hoặc Đăng ký để gửi bình luận.