Есть две проблемы с кодом, который вы представили:
Проблема # 1: Предполагая, что postMessage
передает ссылку, но вместо этого она сериализует / десериализует ее.
Когда выиспользуя postMessage
из основного js в WebWorker, вы передаете объект HitTemp, а позже, в WebWorker, вы предполагаете, что если вы зададите свойства этого объекта, исходный объект также будет изменен.Под этим я подразумеваю следующий код:
firstWorker.postMessage([
HitTemp // <-- here you are sending the object to the WebWorker
, HitTemp.playerCurrent, maxNodes]);
workerScript = URL.createObjectURL( new Blob( [ `
// ...
if (e > evalFinal) {
HitCurrent.coordPlayable = [i,j]; // <-- here you access the object
evalFinal = e;
}
//...
К сожалению, согласно документации , при вызове postMessage
исходный объект сериализуется вызывающей стороной и затем десериализуется в WebWorker.Таким образом, WebWorker эффективно работает с копией.К счастью, этого легко избежать, разместив данные, которые вас больше всего интересуют, внутри postMessage
назад из WebWorker.
Проблема №2: Использование переменных a
и b
вне области действия
Я заметил, что вы пытаетесь получить доступ к значениям, которые определены в обратном обратном вызове .then()
вне этого обратного вызова, например:
//...
} ).then( ( { result } ) => {
let [ a, b ] = //here you define a and b
} );
// a and b are no longer in scope here
for (k = 0; k < 8; k++) {
exploreHitLine(HitCurrent, a, b, k, 'drawing');
}
Решение
Чтобы решитьВо-первых, вам нужно вернуть значения HitCurrent
(которые содержат coordPlayable
, которые вас, вероятно, больше всего интересуют) с postMessage
обратно из WebWorker.Для второй проблемы просто переместите заключительный цикл for
, используя переменные a
и b
внутри обратного вызова .then()
.Код результата выглядит следующим образом:
Основной код JS:
new Promise( resolve => {
let HitTemp = JSON.parse(JSON.stringify(HitCurrent));
let firstWorker = new Worker( workerScript );
firstWorker.onmessage = function ( event ) {
resolve( event.data );
console.log('here5');
}
firstWorker.postMessage([HitTemp, HitTemp.playerCurrent, maxNodes]);
} ).then( ( { result } ) => {
var HitResult = result.HitResult;
let [ a, b ] = HitResult.coordPlayable; // <-- get values from result
console.log('result3 : ', result.eval);
console.log('here3 : ', a, b);
//move for loop inside the callback
for (k = 0; k < 8; k++) {
exploreHitLine(HitCurrent, a, b, k, 'drawing');
}
} );
WebWorker:
window.onload = function() {
// Inline webworker version
workerScript = URL.createObjectURL( new Blob( [ `
"use strict";
// ...
function negaMax(HitCurrent, colorCurrent, depth) {
// Indices
var i, j, k;
// Evaluation
var arrayTemp, evalFinal, e;
// Set current color to HitCurrent
HitCurrent.playerCurrent = colorCurrent;
// Deep copy of arrayCurrent array
arrayTemp = JSON.parse(JSON.stringify(HitCurrent.arrayCurrent));
// If depth equal to 0
if (depth == 0)
return evaluation(HitCurrent);
// Starting evaluation
evalFinal = -infinity;
// Compute all playable hits and check if playable hits
if (computeHit(HitCurrent, 'playable')) {
// Browse all possible hits
for (i = 0; i < 8; i++)
for (j = 0; j < 8; j++)
if (HitCurrent.arrayPlayable[i][j] == 'playable') {
for (k = 0; k < 8; k++) {
// Explore line started from (i,j) with direction "k"
exploreHitLine(HitCurrent, i, j, k, 'drawing');
}
// Recursive call
e = -negaMax(JSON.parse(JSON.stringify(HitCurrent)).eval, ((JSON.stringify(HitCurrent.playerCurrent) == JSON.stringify(playerBlack)) ? playerWhite : playerBlack), depth-1); //since negaMax returns an object, don't forget to access the value in the recursive call
if (e > evalFinal) {
HitCurrent.coordPlayable = [i,j];
evalFinal = e;
}
if (e == -infinity) {
HitCurrent.coordPlayable = [i,j];
}
// Restore arrayCurrent array
HitCurrent.arrayCurrent = JSON.parse(JSON.stringify(arrayTemp));
}
// Clean playable hits once double loop is done
cleanHits('playable', HitCurrent);
}
console.log('here2 :', evalFinal);
return {eval: evalFinal, HitResult: HitCurrent }; //<-- send the additional HitCurrent as a result here
}
onmessage = function ( event ) {
let params = event.data;
postMessage( { result: negaMax( ...params ) } );
};
` ], { type: "plain/text" } ) );
main();
}
Я решил вернуть целое HitCurrent
изнутри WebWorkerи передается как HitResult
параметр, потому что на основании того факта, что другие параметры также изменяются рекурсивным методом (например, arrayPlayable
и arrayCurrent
), вы также сможете получить измененные значения после вычисления.