16

Firstly I want to ask if this is possible or not,Setting value to global variable inside async function or promise?

If yes then why does every available tutorial/website uses console.log(results) in the tutorial but never uses it to assign it to variable.

For example:

var promise1 = new Promise(function(resolve, reject) {
    resolve('foo');
});
let myval="";
promise1.then(function(value) {
 myval=value;
  console.log(value); // this logs "foo"
});

console.log(myval); //this logs blank
Prabhjot Singh Kainth
  • 1,831
  • 2
  • 18
  • 26
  • Are you aware that `//this logs blank` is called before `//this logs "foo"` because of the delay caused by the promise? – Swimmer F Dec 25 '19 at 10:38
  • Yes I am pretty much aware of that. My question is how can I assign value to variable myval (assume myval to be global). – Prabhjot Singh Kainth Dec 25 '19 at 10:40
  • 1
    the code is not the problem but the interpretation is. If you need the global variable set to something inside the promise, there are two ways to handle this - Wait for some random time which is obviously not 100% correct as it may or maynot work. Depends on how much time promise takes to resolve - If you really need global variable, make sure you use them in the promise chain. So in your example instead of doing console log outside promise chain, do it as a next then and use. – Ashish Modi Dec 25 '19 at 11:00

3 Answers3

11

If you want to access the changed version of myval (that is, execute your code after the assignment inside the Promise has been done), you need to either follow up with yet another then, or do anything else that'd put your code in the event queue after the assignment.

var promise1 = new Promise(function(resolve, reject) {
    resolve('foo');
});
let myval="a";
promise1.then(function(value) {
 myval=value;
  console.log(value); // this logs "foo"
});

setTimeout(() => console.log(myval), 0); // logs "foo"
var promise1 = new Promise(function(resolve, reject) {
    resolve('foo');
});
let myval="a";
promise1.then(function(value) {
 myval=value;
  console.log(value); // this logs "foo"
}).then(function() {
    console.log(myval) // logs "foo"
});

And an await example, probably the one you're looking for:

  • wrap everything into an immediately invoked async function, so we can use await inside
  • save the .then promise into a variable (you can, obviously, omit that variable altogether and await directly)
  • await that promise before your console.log
(async () => {
    var promise1 = new Promise(function(resolve, reject) {
        resolve('foo');
    });
    let myval="";
    var thenedPromise = promise1.then(function(value) {
     myval=value;
      console.log(value); // this logs "foo"
    });

    await thenedPromise; // wait before the promise generated by "then" is resolved

    console.log(myval); // logs "foo"
})();
John Smith
  • 3,863
  • 3
  • 24
  • 42
2

That would change the global variable myval to 'foo' but by the time console.log(myval); is called the promised has not yet been resolved because of the timeout and even if you resolve the promise immediately it will still only change it after the console.log(myval); has run because the promise will be queued as a microtask.

I would add a setTimeout to wait for the assignment or a setInterval to check for when it happens.

var promise1 = new Promise(function(resolve, reject) {
resolve('foo');});
let myval="";
promise1.then(function(value) {
  myval=value;
  console.log(value); // this logs "foo"
});

setTimeout(() => console.log(myval), 1000); //this logs 'foo'
Ogie
  • 1,304
  • 2
  • 14
  • 17
  • My question is how can I assign the value to myval . I know about promises. – Prabhjot Singh Kainth Dec 25 '19 at 10:41
  • That is what my answer confirms that it would still change/assign the value to `myval`. If you want to use it then you have to wait for the assignment to take place. For example checking it in a `setInterval` – Ogie Dec 25 '19 at 10:44
  • I have updated my question, I have removed setTimeout . Still it won`t set value to myval. – Prabhjot Singh Kainth Dec 25 '19 at 10:46
  • You are not getting my question. Just forget about console.log(myval). I am asking how to assign the value to myval ??? How can I do this?? – Prabhjot Singh Kainth Dec 25 '19 at 10:51
  • @PrabhjotSinghKainth You are assigning to myval, but the bottom console.log happens before the value is assigned (because the promise.then is executed not immediately, but put into the queue - everything in .then is executed AFTER the main code). Read up about Node's asynchrony. – John Smith Dec 25 '19 at 10:54
  • @JohnSmith I understand that thing pretty well. I want to use myval variable somewhere else in my code , but at that point also it is blank . Also I have used await still doesnot works. – Prabhjot Singh Kainth Dec 25 '19 at 10:55
  • See this question of mine also https://stackoverflow.com/questions/59476582/value-is-not-getting-inserted-in-the-array-array-returns-blank-values/59476618?noredirect=1#comment105131574_59476618 – Prabhjot Singh Kainth Dec 25 '19 at 10:56
  • @PrabhjotSinghKainth seconding the above comment by John Smith, your program does what you are trying to do, it's just your testing/debugging that isn't working as intended – Swimmer F Dec 25 '19 at 10:56
2

It is all about javascript's async behavior. See the below snippet and notice the execution sequence. value is already assigning to myval after resolving the promise. In your case, you just need to maintain a flag whether that particular promise is resolved or not then after if you will try to get the value of myval variable you will your desired output. And yes, it is one of the many ways of achieving this.

let myval="";
var promise1 = new Promise(function(resolve, reject) {
    resolve('foo');
});
promise1.then(function(value) {
    myval=value;
    console.log("Value :" + value);
    console.log("myval after promise : " + myval);
});

console.log("myval before promise : " + myval);
Keyur Ramoliya
  • 1,900
  • 2
  • 16
  • 17