Search code examples
javascriptasynchronouspromiseweb-worker

Javascript - Local object variable not conserved between promise and await


I am using the code below which higlights the fact that local object variable (HitCurrent) is not conserved between the core of computeHit(HitCurrent,'computer') and after the calling of this function in the following way : await computeHit(HitCurrent, 'computer');

In the core of computeHit(HitCurrent,'computer'), array HitCurrent.arrayCurrent is modified (actually, it computes the hit for computer) : But the issue is that modifications are not conserved once I come back to the main thread (after await computeHit(HitCurrent, 'computer').

If I do, after the await, a console.log of an array contained in this local object variable, I don't get the same array than one which is right computed into core of computeHit function. I don't understand this behavior.

// Perform hit computer
(async () => {
// Wait computeHit function
await computeHit(HitCurrent, 'computer');

// Output array which is not the same than into computeHit 
console.log('into async : HitCurrent.arrayCurrent', HitCurrent.arrayCurrent);
alert('into async() function');
})();

}

with computerHit function like :

function computeHit(HitCurrent, mode) {

if (mode == 'computer') {

return new Promise( resolve => {
// Creation of webworker
let firstWorker = new Worker(workerScript);
firstWorker.onmessage = function (event) {
  resolve(event.data);
}
// Post current copy of HitCurrent, i.e HitCurrent
firstWorker.postMessage([HitCurrent, HitCurrent.playerCurrent, maxNodes]);
}).then(({result}) => {

// Get back game board of webworker
HitCurrent = result.HitResult;

// Get back suggested hit computed by webworker
[a,b] = HitCurrent.coordPlayable;

// Drawing all lines from suggested hit (in 8 directions)
// HitCurrent.arrayCurrent is modified HERE !
for (k = 0; k < 8; k++) {
   exploreHitLine(HitCurrent, a, b, k, 'drawing');
}

// Remove playable hits
cleanHits('playable', HitCurrent);

// Display current game
displayCurrentHit(HitCurrent);

// Output array which is good
alert('into computeHit function');
console.log('into promise - HitCurrent.arrayCurrent', HitCurrent.arrayCurrent);
})
}
}

I expect to get back the same array (i.e HitCurrent.arrayCurrent) between the computation of it into computeHit function and after the await call, but this is not the case.

How could I fix this issue ? I tried to pass by global variables, without success. Feel free to ask me further informations if you need it.


Solution

  • Let's rewrite your code just a little and rename some variables. Literally, I've renamed the parameters of computeHit(..) to my_variable_1 and my_variable_2. You may want to check/admit this does not change the code execution.

    You should now understand why the HitCurrent in your async code block is never modified. Refer to simplified code block 3, which will yield 42. Hope it helps.

    Code block 1 unchanged :

    // Perform hit computer
    (async () => {
    // Wait computeHit function
    await computeHit(HitCurrent, 'computer');
    
    // Output array which is not the same than into computeHit 
    console.log('into async : HitCurrent.arrayCurrent', HitCurrent.arrayCurrent);
    alert('into async() function');
    })();
    

    Code block 2 with renamed variables :

    function computeHit(my_variable_1, my_variable_2) {
    
    if (my_variable_2 == 'computer') {
    
    return new Promise( resolve => {
    // Creation of webworker
    let firstWorker = new Worker(workerScript);
    firstWorker.onmessage = function (event) {
      resolve(event.data);
    }
    // Post current copy of my_variable_1, i.e my_variable_1
    firstWorker.postMessage([my_variable_1, my_variable_1.playerCurrent, maxNodes]);
    }).then(({result}) => {
    
    // Get back game board of webworker
    my_variable_1 = result.HitResult;
    
    // Get back suggested hit computed by webworker
    [a,b] = my_variable_1.coordPlayable;
    
    // Drawing all lines from suggested hit (in 8 directions)
    // my_variable_1.arrayCurrent is modified HERE !
    for (k = 0; k < 8; k++) {
       exploreHitLine(my_variable_1, a, b, k, 'drawing');
    }
    
    // Remove playable hits
    cleanHits('playable', my_variable_1);
    
    // Display current game
    displayCurrentHit(my_variable_1);
    
    // Output array which is good
    alert('into computeHit function');
    console.log('into promise - my_variable_1.arrayCurrent', my_variable_1.arrayCurrent);
    })
    }
    }
    

    Code block 3, simplified :

    // Perform hit computer
    var magicNumber = 42;
    (async () => {
        await computeHit(magicNumber, 'computer');
        console.log('magic is ', magicNumber);
    })();
    
    function computeHit(my_variable_1, my_variable_2) {
        if (my_variable_2 == 'computer') {
            // Get back game board of webworker
            my_variable_1 = 314159;
        }
    }