Javascript 递归函数的Webworker
我已经从一篇旧帖子()中找到了一些答案 现在我接管这个暗示这个问题的小代码。这段小代码使用内联webworkers,因为我使用了一个递归函数来计算最佳点击率(这是“计算机”点击率)。如果我不使用webworker,而且深度太高,游戏就会挂在浏览器上 代码源代码可在[此链接][1]上获得 我想得到一个工作代码。事实上,我已经接近解决方案,因为已经修复了几个bug(例如,在webworker中包含不同的函数,使其在不调用外部函数的情况下进行计算。如果我没有包含所有必要的函数,webworker将无法工作,因为它有自己的作用域 因此,我想获得调试当前版本的帮助 游戏可在[此链接][2]上下载 我只对“计算机对播放器”模式感兴趣(黑色开始播放)。在下面,你可以找到我调用递归函数时的部分 使用这个递归函数完成计算后,我想返回表示当前游戏地图的对象(黑色/白色圆圈的位置) 为了返回对象或建议命中的坐标(这里是主函数),我执行了以下代码:Javascript 递归函数的Webworker,javascript,recursion,web-worker,Javascript,Recursion,Web Worker,我已经从一篇旧帖子()中找到了一些答案 现在我接管这个暗示这个问题的小代码。这段小代码使用内联webworkers,因为我使用了一个递归函数来计算最佳点击率(这是“计算机”点击率)。如果我不使用webworker,而且深度太高,游戏就会挂在浏览器上 代码源代码可在[此链接][1]上获得 我想得到一个工作代码。事实上,我已经接近解决方案,因为已经修复了几个bug(例如,在webworker中包含不同的函数,使其在不调用外部函数的情况下进行计算。如果我没有包含所有必要的函数,webworker将无法
// Call the recursive function and get final (a,b) results
new Promise( resolve => {
let HitTemp = JSON.parse(JSON.stringify(HitCurrent));
let firstWorker = new Worker( workerScript );
firstWorker.onmessage = function ( event ) {
resolve( event.data ); //{ result: XXX }
console.log('here5');
}
firstWorker.postMessage([HitTemp, HitTemp.playerCurrent, maxNodes]);
} ).then( ( { result } ) => {
//let [ a, b ] = result.coordPlayable;
let [ a, b ] = HitTemp.coordPlayable;
console.log('result3 : ', result);
console.log('here3 : ', a, b);
} );
// HERE I TRY TO USE a and b in exploreHitLine function
// who needs the variables a and b BUT I DON'T KNOW
// IF a AND b ARE KNOWN HERE FROM CODE ABOVE
for (k = 0; k < 8; k++) {
exploreHitLine(HitCurrent, a, b, k, 'drawing');
}
//调用递归函数并获得最终(a,b)结果
新承诺(解决=>{
让HitTemp=JSON.parse(JSON.stringify(HitCurrent));
让firstWorker=newworker(workerScript);
firstWorker.onmessage=函数(事件){
解析(event.data);//{result:XXX}
console.log('here5');
}
firstWorker.postMessage([HitTemp,HitTemp.playerCurrent,maxNodes]);
})。然后({result})=>{
//设[a,b]=result.coordPlayable;
设[a,b]=HitTemp.coordPlayable;
log('result3:',result);
console.log('here3:',a,b);
} );
//在这里,我尝试在exploreHitLine函数中使用a和b
//谁需要变量a和b,但我不知道
//如果从上面的代码中知道a和b
对于(k=0;k<8;k++){
探索性地契线(当前、a、b、k,‘图纸’);
}
在递归函数下面(在内联webworker部分内):
window.onload=function(){
//内联webworker版本
workerScript=URL.createObjectURL(新Blob([`
“严格使用”;
...
...
//内联webworker所需的所有其他变量和函数
...
...
...
函数negaMax(HitCurrent、colorCurrent、depth){
//指数
变量i,j,k;
//评价
var arrayTemp,evalFinal,e;
//将当前颜色设置为当前颜色
HitCurrent.playerCurrent=彩色电流;
//arrayCurrent阵列的深度复制
arrayTemp=JSON.parse(JSON.stringify(HitCurrent.arrayCurrent));
//如果深度等于0
如果(深度==0)
返回评估(当前);
//开始评估
evalFinal=-无穷大;
//计算所有可播放的点击,并检查是否可播放点击
if(computeHit(HitCurrent,'playable')){
//浏览所有可能的点击
对于(i=0;i<8;i++)
对于(j=0;j<8;j++)
if(HitCurrent.ArrayPlayible[i][j]=“可播放”){
对于(k=0;k<8;k++){
//从(i,j)开始探索方向为“k”的直线
exploreehitline(当前,i,j,k,'图纸');
}
//递归调用
e=-negaMax(JSON.parse(JSON.stringify(HitCurrent)),((JSON.stringify(HitCurrent.playerCurrent)==JSON.stringify(playerBlack))?playerWhite:playerBlack),depth-1);
如果(e>evalFinal){
HitCurrent.coordPlayable=[i,j];
evalFinal=e;
}
if(e==-无穷大){
HitCurrent.coordPlayable=[i,j];
}
//还原阵列当前阵列
HitCurrent.arrayCurrent=JSON.parse(JSON.stringify(arrayTemp));
}
//完成双循环后,清除可播放的命中
清除命中(“可播放”,当前命中率);
}
console.log('here2:',evalFinal);
返回评估结果;
}
onmessage=函数(事件){
设params=event.data;
//postMessage({result:recursiveFunction(HitCurrent,HitCurrent.playerCurrent,maxNodes)});
postMessage({result:negaMax(…params)});
};
`],{type:“纯文本”});
main();
}
我希望通过递归函数返回计算值的坐标“a”和“b”,但它似乎什么也不返回
我不知道如何接收对象HitTemp
对象,或者更直接地获取a
和b
建议的坐标
如果您不理解我在这个算法中的问题,请随时询问我更多的精确性。您介绍的代码有两个问题: 问题#1:假设
postMessage
传递了一个引用,但它将其序列化/反序列化。
当您在主js中使用postMessage
时,您将传递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;
}
//...
解决方案
要解决第一个问题,您需要返回HitCurrent
的值(其中包含您可能最感兴趣的coordPlayable
)从WebWorker返回postMessage
。对于第二个问题,只需使用中的a
和b
变量移动For
循环的最后一个。然后()
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;
}
//...
//...
} ).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');
}
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');
}
} );
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();
}