0

I'm trying to get a closure to return a value that is supposed to be updated once a promise is resolved (or rejected).

The following code works. Initially the internal variable from within the close returns NONE as expected.

Then the first Promise is launched, and once that is resolved, the internal variable is updated to FAIL.

The second Promise is a deliberate delay, just so that we can observe the change of the closured variable.

However, once the while loop is added to the equation, by uncommenting that loop(x) section, the update is not observable within the while loop.

I would expect to see this:

...
9963000000 NONE
9964000000 NONE
9965000000 NONE
9966000000 NONE
9967000000 NONE
9968000000 FAIL
9969000000 FAIL
9970000000 FAIL
9971000000 FAIL
9972000000 FAIL
9973000000 FAIL
9974000000 FAIL
...

I know it might be due to the single threaded blocking, but, is there a way to observe a dynamic external variable from within the while loop?

let sleep = async (ms) => new Promise ((resolve, reject) => setTimeout (resolve, ms));

let task = async (ms) => new Promise (function(resolve, reject) {
    setTimeout (function(){
        const error = true;
        let result;
        if(error){
            result = '_NO_';
            reject({'state': false, 'response': result});
        }else{
            result = '_YES_';
            resolve({'state': true, 'response': result});
        }
    }, ms);
});

let loop = async (cb) => {
    let i = 0;
    while(i<10000000000){
        const value = cb.getResponse();
        (function() {
            if(i%1000000==0){ console.log(i, value) };
            i += 1;
        })(i, value);
    }
}

const linkResponse = (function(){
    let response = 'NONE';
    function setResponse(value) {response = value; return response};
    function getResponse() {return response};
    return { 'setResponse': setResponse, 'getResponse': getResponse };
});

const x = linkResponse();
console.log(x.getResponse());

(async () => {
    task(3000)
        .then(function(res){
            console.log('__OK__', res);
            let response = 'SUCCESS';
            x.setResponse(response)
        })
        .catch(function(err){
            console.log('error', err);
            let response = 'FAIL';
            x.setResponse(response)
        });

    sleep(6000)
        .then(function(res){
            console.log(x.getResponse())
        });

    //loop(x);
})();
mbilyanov
  • 2,315
  • 4
  • 29
  • 49
  • 1
    While loops are indeed blocking the thread and nothing will get executed until that loop is done. There is a very good explanation in stack overflow: https://stackoverflow.com/a/34825352/10101082 So it seems like your async function isn't being executed until the while loop is over. Also, may I ask, while would you use a while loop? – Simon Ifergan Jun 27 '20 at 19:51
  • Yes. It was just a wrong way to test this issue. I have solved the problem using a recursive function call. I just needed to emulate a background task that was NOT a promise and was still taking some time. – mbilyanov Jun 27 '20 at 20:05
  • I ended up using a recursive function, but that ended up with a `RangeError: Maximum call stack size exceeded` error. At the end, I had the use a Promise based `sleep()` in there to fix the problem. It is not as fast as a `while` loop, but does the job for now. If anyone knows how I can solve this problem without running into the `RangeError` issue, that would be amazing. – mbilyanov Jun 27 '20 at 20:23
  • I just need something that will count infinitely and be fast - without the need to `sleep()` - and will still be able to access external changes to states. – mbilyanov Jun 27 '20 at 20:26

1 Answers1

0

Well, thanks for the help. Just as I was suspecting, it is indeed a blocked thread issue. I solved the problem with a recursive function. I just needed to have a long process running in the background and I naively thought that an infinite loop will do the job.

let loop2 = function(i, cb) {
    if(i>100000){
        return
    }
    console.log(i, cb.getResponse());
    i += 1;
    sleep(0)
        .then(function(res){
            loop2(i, cb);
        });
}

And then calling:

loop2(0, x);
mbilyanov
  • 2,315
  • 4
  • 29
  • 49