setTimeout() a rare crtiier

Status
Niet open voor verdere reacties.

e-mail-user

Gebruiker
Lid geworden
24 apr 2007
Berichten
133
Het volgende is een deel van m'n code:
Code:
				setTimeout(function() {
					alert('setTimeout werkt');
					this._banaanFunction();
					this._mamaFunction();
					this._papaFunction(); 
				}, 3000);

				return BoardModel.SECOND;
			};
		};
	};
};


_p._banaanFunction = function() {
	alert('banaan werkt');
	this._tileIdArray.length = 0;
};

_p._mamaFunction = function() {
	alert('mama het werkt');
	this._tileIdArray.length = 0;
};

_p._papaFunction = function() {
	alert('papa het werkt');
	this._tileIdArray.length = 0;
};
Het vreemde is dat alleen de alert zichtbaar wordt.
Schermafbeelding 2015-08-16 om 13.01.17.png
Vragen:
1.
Kent iemand dit verschijnsel?
2.
Wat doe je eraan?
Alle hulp is welkom.
 
setTimout voert de opgegeven functie uit in global/window scope: this zal dan ook naar het global object verwijzen en niet naar jouw speciale variabele.

mogelijkse oplossingen liggen in het gebruik van bind en/of closures
 
Ik heb (uiteindelijk!) een oplossing gevonden voor m'n probleem.
Javascript voert nu de functie restoreCellArray() uit NA de functie restoreGameStatus().
Dat is ten minste iets; ben ik nu gelukkig?
Nou nee, ik vind het maar een "houtje touwtje" oplossing.
Code:
_p._restoreGameStatus = function() {
	
	var cellArray = this._boardModel.getCellIdArray(),	// id's flipped cells
		cols      = this._boardModel.getCols(),
		that      = this;
	
	setTimeout(function() {
	
		console.log('restoreGameStatus');
		
		for(var i = 0; i < 2; i++) {
			var col      = cellArray[i] % cols,
				row      = Math.floor(cellArray[i] / cols),
				cellId   = cellArray[i];
				
			that._boardModel.resetTileSide(cellId);
			
			console.log('tileData.side: '+that._boardModel.getTileData(cellId).side+'\n'+
						'i='+i+' cellArray[i]: '+cellArray[i]+'\n'+
						'i='+i+' col: '+col+' row: '+row);
				
			drawParams = that._boardRenderer.getDrawParams(col, row);
			that._boardRenderer.drawOneImage(drawParams);

		};	// for-loop
	
	}, 3000);
	
	setTimeout(this._restoreCellArray.bind(this), 4000);
	
};	// restoreGameStatus

_p._restoreCellArray = function() {

	console.log('restoreCellArray');	
	
	this._boardModel.resetCellIdArray();
};
Mijn vraag is: kan dit anders?
Eleganter, zonder twee keer setTimeout() achter elkaar te gebruiken.
 
Puur op dit sample, zie ik niet in waarom je setTimout gebruikt, aangezien het lijkt neer te komen op alles sequentieel uitvoeren (tenzij de call naar restoreCellArray bewust ong 1s vertraagd moet worden).

Poging tot herschrijven:[JS]_p._restoreGameStatus = function() {
var cellArray = this._boardModel.getCellIdArray(), // id's flipped cells
cols = this._boardModel.getCols(),
cellId, row, col; //JS heeft functionscope, nu worden deze variabelen slechts 1 maal gealloceerd en dan herbruikt

console.log('restoreGameStatus');

for(var i = 0; i < 2; i++) {
cellId = cellArray;
row = Math.floor(cellId / cols);
col = cellId % cols;

this._boardModel.resetTileSide(cellId);

console.log('tileData.side: ' + this._boardModel.getTileData(cellId).side + '\n'
+ '\ti=' + i + ' cellId: ' + cellId + '\n'
+ '\ti=' + i + ' col: ' + col + ' row: ' + row);

this._boardRenderer.drawOneImage(this._boardRenderer.getDrawParams(col, row));
}; // for-loop

this._restoreCellArray();
//of als je de 1s vertraging nodig hebt:
//setTimeout(this._restoreCellArray.bind(this), 1000);

/*of via een closure met self-executing functions:
setTimeout((function(that){
return (function() {
that._restoreCellArray();
});
})(this), 1000);
*/

}; // restoreGameStatus

_p._restoreCellArray = function() {
console.log('restoreCellArray');
this._boardModel.resetCellIdArray();
};[/JS]
 
Johantrax,
De functie restoreGameStatus() tekent twee plaatjes op het canvas; daarna moet de hele handel ca twee seconden wachten om de speler de gelegenheid te geven die plaatjes te memoriseren.
restoreCellArray() moet waarden resetten die voor het tekenen in restoreGameStatus() nodig zijn.
Een soort "kip en ei" probleem derhalve.

Ik heb je suggesties toegepast, maar dan werkt het niet meer.
Er verschijnt maar een (1) plaatje; en dat verdwijnt na de vertraging.
 
Laatst bewerkt:
Hmm.. nochtans heb ik strikt genomen niks aan je logica veranderd (behalve het verwijderen van de timeout).
Het zou natuurlijk wel kunnen dat het clearen van plaatje 2 nu zo snel volgt op het tekenen ervan, dat je het als speler gewoonweg niet kan zien. Ik stel voor dat je [JS]this._restoreCellArray();
//of als je de 1s vertraging nodig hebt:
//setTimeout(this._restoreCellArray.bind(this), 1000);[/JS] dan wijzigt in [JS]setTimeout(this._restoreCellArray.bind(this), 2000);[/JS]
Mijn excuses als je dat al geprobeerd zou hebben, ik kan het niet duidelijk opmaken uit je post.

Klopt de console-output wel met wat je verwacht?
En kan je eventueel een versie van je project online zetten (bvb via jsfiddle)? Ik begin op een punt te komen waar het moeilijk wordt om puur op een fragment code advies te geven.
 
Johantrax,
Ik zal een versie verzorgen die ik op m'n website zet.
Dat moet sowieso een keer gebeuren.

Done!
Zie: http://www.philippina.nl/memory
Dit is nog een voorlopige versie dus verwacht geen wonderen.
Na de nodige inspanning is het exploderen van het GameOver plaatje gelukt.
Het wachten en laten verdwijnen van twee verschillende plaatjes is nog op de hierboven aangegeven manier.
 
Laatst bewerkt:
Ik heb via de developer tools volgende aanpassing doorgevoerd, wat in Vivaldi lijkt te werken (en dus vermoedelijk ook op chrome):[JS]// restoreGameStatus
_p._restoreGameStatus = function() {

var cellArray = this._boardModel.getCellIdArray(), // id's flipped cells
cols = this._boardModel.getCols(),
that = this;

setTimeout(function() {
console.log('restoreGameStatus');
for(var i = 0; i < 2; i++) {
var col = cellArray % cols,
row = Math.floor(cellArray / cols),
cellId = cellArray;
that._boardModel.resetTileSide(cellId);
console.log('tileData.side: '+that._boardModel.getTileData(cellId).side+'\n'+
'i='+i+' cellArray: '+cellArray+'\n'+
'i='+i+' col: '+col+' row: '+row);
var drawParams = that._boardRenderer.getDrawParams(col, row);
that._boardRenderer.drawOneImage(drawParams);
}; // for-loop
that._restoreCellArray();
}, 1500);

//setTimeout(this._restoreCellArray.bind(this), 2000);

}; // restoreGameStatus[/JS]
De tweede setTimeout lijkt dus helemaal niet nodig; wanneer de for-loop is afgelopen is alle nodige info verwerkt en kan je restore meteen aanroepen.
 
Status
Niet open voor verdere reacties.

Nieuwste berichten

Terug
Bovenaan Onderaan