1

Before anyone asks if I reviewed other questions, I did find this one (link below paragraph) and updated one of my variables because it was redeclared as a local variable. It should now be hoisted as a global with precedence.

Global variable in function not updating

I'm basically trying to get a Next Payment Time for a crypto-mining website. Currently, I'm able to grab the Last Payment Time and Payment Interval. The math isn't the issue... the problem I run in to is that when I grab the variables (from inside a function, they are not updating the global one.

Original Declaration @ Global

<script>
        let pendingPaymentTrigger = false;
        let timeInterval = 0;
        let pendingPayment = 0;
 /** Script Below **/

Then we break into the function, which I'm redacting due to most of it not being relevant to recreate the issue.

function values(baseAPI, minersAPI, activeMinersAPI, workersAPI) {
            if (window.location.href.indexOf("address") > -1) {
                const urlParams = new URLSearchParams(window.location.search);
                const wallet = urlParams.get('address');
                yourAPI = minersAPI + "?method=" + wallet;
                $("#walletRequest").hide();
                $("dashboardDisplay").show();
                const XHR = new XMLHttpRequest();
                XHR.open("GET", yourAPI, true);
                XHR.onload = function() {
                    if (this.status === 200) {
                        obj = JSON.parse(this.responseText);
                    if (obj.body.primary?.payments?.balances === undefined || obj.body.primary?.payments?.generate === undefined) {
                            document.getElementById('pendingPayments').innerHTML = "Innactive";
                    } else {
                        document.getElementById('pendingPayments').innerHTML = Math.round((obj.body.primary.payments.balances + obj.body.primary.payments.generate + obj.body.primary.payments.immature) * 100) / 100 + " HVQ";
                        pendingPaymentTrigger = true;
                        pendingPayment = Math.round((obj.body.primary.payments.balances + obj.body.primary.payments.generate + obj.body.primary.payments.immature) * 100) / 100;
                        console.log(pendingPayment);
                    }

At this point, the console shows '1 Hour' || If I change from pendingPayments to pendingPaymentTrigger it shows 'True'

Right after the function ends...

}
console.log(pendingPayment);


let displayBlocks = new Array();
let displayBlocks2 = new Array();

function checkBlocks() { // This is the next function - not relevant, but supporting that I am **out** of the last function.

This console shows '0' (the original global variable).

I'm guessing it has something to do with hoisting but I can't figure out where the issue lies..


Tested theory from comments 1 - moving to the end of the function:

if (obj.body.primary?.payments?.balances === undefined || obj.body.primary?.payments?.generate === undefined) {
            document.getElementById('pendingPayments').innerHTML = "Innactive";
        } else {
            document.getElementById('pendingPayments').innerHTML = Math.round((obj.body.primary.payments.balances + obj.body.primary.payments.generate + obj.body.primary.payments.immature) * 100) / 100 + " HVQ";
            pendingPaymentTrigger = true;
            pendingPayment = Math.round((obj.body.primary.payments.balances + obj.body.primary.payments.generate + obj.body.primary.payments.immature) * 100) / 100;
            console.log(pendingPayment);
        }
    }
};
XHR.send();

This did not change the outcome - has time here, but not after.

jpgerb
  • 1,043
  • 1
  • 9
  • 36
  • 2
    could it be that `pendingPayment` is being updated after it's logged in the console? XHR requests are async the onload callback will run when the request is done, by that time it will already have logged `0` since unlike PHP, JS has an event loop – Asplund Apr 29 '22 at 16:49
  • @Undo I moved it to the end of the function - just before the `XHR.send();` and no change. – jpgerb Apr 29 '22 at 16:53
  • 3
    JS is not a synchronous language, it will not wait for the onload event to be called before continuing to execute. – Asplund Apr 29 '22 at 16:54
  • so you're saying it's running right past my `local` version of the variables and getting overwritten by the `global` version before the `function` / `onload` finishes? – jpgerb Apr 29 '22 at 16:57
  • 1
    no, I think you're just logging the variable before it changes – Asplund Apr 29 '22 at 16:58
  • Possible - so we know that the variable is changing to '1 Hour' at some point (initially set to 0). We know it's not making it to the bottom of my `` (which is where I'm testing the final value). I guess the question would be - how do I get it down there... – jpgerb Apr 29 '22 at 17:00
  • 1
    You need to either use `async/await` logic or nest your operation inside the XHR.onload. XHR.onload overwrites your global variables, the problem is that console.log runs before the XHR request has finished, since XHR is async – savageGoat Apr 29 '22 at 17:01
  • 1
    you can make a new function *down there* and call that function after mutating the variable in your callback – Asplund Apr 29 '22 at 17:01
  • I do like the idea of another function - nice and clean that way - if you want to throw that as an answer, I'll accept it @Undo – jpgerb Apr 29 '22 at 17:03

1 Answers1

1

You can declare a function after your script and call that function when the XHR request is done and you've mutated the variable.

/* ... */
pendingPaymentTrigger = true;
pendingPayment = Math.round((obj.body.primary.payments.balances + obj.body.primary.payments.generate + obj.body.primary.payments.immature) * 100) / 100;
doSomething();
/* ... */
function doSomething() {
    console.log(pendingPayment);
}
Asplund
  • 2,254
  • 1
  • 8
  • 19
  • If you do that, better pass the value as an argument instead of relying on a global variable. – Bergi Apr 29 '22 at 18:22
  • I agree but OP might have other reasons for using a global variable – Asplund Apr 29 '22 at 18:45
  • The functions do so many things together. I consolidated 6 different APIs into 2 functions (5 and 1) - It would be difficult to grab the data I need and `return` it back. In addition, I've noticed that the vars done even make it out of the `XHR`. I tried doing @Undo 's suggestion, and the end result was the same. – jpgerb Apr 29 '22 at 18:59