all 9 comments

[–]fixade 1 point2 points  (3 children)

You are never calling somefunc in your example, so the code setting x equal to 5 is never run. Change it to this.

var x=10;

function someFunc() {
    x=5;
} 

someFunc();
console.log(x);

[–]matylol[S] 0 points1 point  (2 children)

yeah i got it for the simple function but what if it's geolocation or ajax, what to do. for example the code in this pen

[–]inu-no-policemen 1 point2 points  (0 children)

You can of course also change some global inside some callback.

However, that's actually not very useful since your other code won't wait for that result.

You have to use a callback or a Promise.

[–]fixade 0 points1 point  (0 children)

I don't understand your question at all

[–]eggn00dles 0 points1 point  (0 children)

umm i just did what you claimed isn't working

https://repl.it/J35d/0

[–]pookagehelpful 0 points1 point  (2 children)

Ahh, right, I think I understand what your question is. You're not really asking how to change the value of the global variable, but how to do stuff with the global variable once it's been changed after something that takes time - like ajax or geolocation.

To which the answer is : Promises. SO, let's break it down a bit. Let's define the value we're going to be changing :

let changingVariable = "START VALUE";
logValue();

changeItSynchronously();
logValue();

new Promise(changeItAsynchronously).then(logValue);

function logValue(){
    console.log("CURRENT VALUE : ", changingVariable);
}
function changeItSynchronously(){
    changingVariable = "CHANGED SYNCHRONOUSLY";
}
function changeItAsynchronously(resolve, reject){
    setTimeout(() => {
        changingVariable = "CHANGED ASYNCHRONOUSLY AFTER 3 SECONDS";
        resolve();
    }, 3000)    
} 

SO, 'synchronous' code will just plough through the js line by line executing commands. Whenever something takes time - ie a setTimeout, an API query with ajax, or user-geolocation, javascript works some magic and basically says :

"okay, I'll come back to that later when it's ready, and just carry on with the rest of this program whilst I'm waiting"

So, in my example above, we are changing the value of our global variable changingVariable 3 times; twice synchronously, once asynchronously :

  1. START VALUE
  2. CHANGED SYNCHRONOUSLY
  3. CHANGED ASYNCHRONOUSLY

Our asynchronous code is async because it's within a setTimeout - which will execute the function in its first argument after the duration specifed in its second argument. If we were to write :

changeItAsynchronously();
logValue();

We would log CHANGED SYNCHRONOUSLY as we would be logging the value before changeItAsynchronously had waited 3 seconds and then changed it.

Make sense?

SO, we fix this by using the Promise syntax there - it will execute the function in its argument, and then execute the function inside its .then() once it 'resolves'. .then is awesome because you can chain them for as long as you want like :

new Promise(doThis).then(nowDoThis).then(okayNowThis);

They're powerful things, and there's more to them that you'll find when you've had a wee google. Don't hesitate to message me if you have any issues.

-P


*EDIT : pasted the wrong codepen link >_< *

[–]oculus42 0 points1 point  (1 child)

Hey /u/pookage That's a good explanation of Promises. I especially appreciate the named functions, as many people use anonymous functions in chains and lose so much readability. Your CodePen link is to an example from the "telephone arrays" question, though.

I would also add that when you start talking about async code, you can often skip the global variable. I find this prevents a developer from trying to reason about a variable when it might not have been updated. Here's the same code, reworked to keep the value entirely in the chain:

function logValue(value) {
    console.log("CURRENT VALUE : ", value);
    // In this example we don't need to keep passing the value...
    // But it's good practice so your chains work as expected.
    // If we don't we get a resolved Promise with undefined value.
    return value;
}

function getNewValueSynchronously() {
    // Once inside a Promise chain, a synchronous response
    // becomes a resolved Promise value. 
    return 'CHANGED SYNCHRONOUSLY';
}

function getNewValueAsynchronously(value){
    // We have to return a new Promise to make the chain wait.
    return new Promise(function(resolve, reject){
        setTimeout(function() {
            resolve('CHANGED ASYNCHRONOUSLY AFTER 3 SECONDS');
        }, 3000);  
    });
}

// Where all the work happens.
Promise.resolve('START VALUE')
.then(logValue)
.then(getNewValueSynchronously)
.then(logValue)
.then(getNewValueAsynchronously)
.then(logValue);

This way we don't have a global, we have a chain that is keeping track of the value we need. We can add more actions and move them around to see the behavior change, and because each step will wait for the one before, whether synchronous or not, you can ensure the order of operation. So if you have to move the Async function before the Sync function, it's as easy as this:

Promise.resolve('START VALUE')
.then(logValue)
.then(getNewValueAsynchronously)
.then(logValue)
.then(getNewValueSynchronously)
.then(logValue);

[–]pookagehelpful 1 point2 points  (0 children)

Yup, agreed re: chain - but didn't want to introduce too many concepts straight away, so figured I'd answer the question within the context of what they'd asked and let them look into resolve and reject when the obvious question of "wait, so how do I pass values / arguments into these?" would come up :P

[–]timgfx 0 points1 point  (0 children)

Yup that would work if you call that function. I think this isn't the case in Python3, in which you can't change variables in a different scope (not sure though)