Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 857
  • Last Modified:

Pause execution in javascript

I have created a class part of which displays an animated gif image in the calling scripts html page, at the same time a sound is streamed from a serever. This is done as follows:

            this.img1Id.src = this.animatedDice;
            startStream (this.diceSound, this.flashProxy);

this part of the code works correctly. Now I need to pause for 2 seconds so the sound has time to finish playing then the animated gif is replaced using the following line of code:

            this.setDiceFace(randomnumber);

This line of code also works correctly but how can I pause between the first 2 lines and the last line of code? This is important so that the class does not return before the sound is finished. I have tried using the timeout function but the class exits before the timer is finished.

As the code stands the animated gif is replaced immediately by the final image (the last line of code).
0
Viking46
Asked:
Viking46
  • 4
  • 4
  • 4
  • +2
3 Solutions
 
daveamourCommented:
I think you can use window.SetTimeOut
https://developer.mozilla.org/en/DOM/window.setTimeout
Run the code you want after the specified pause.
Is this any good?
0
 
daveamourCommented:
SetTimeout actually - no capital O I don't think
0
 
Viking46Author Commented:
Hi,

I have tried that (note where I said that I tried using a timer) but as I am working inside a class the code will finish and return a value before the timer is finished.

Ideas please

Thanks
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
OnthraxCommented:
This might do the trick for you.

pause(milliseconds)


function pause(millisecs) {
  var future = new Future();
  setTimeout(function() {
    future.fulfill()
  },millisecs);
  future.suspend();
}

Open in new window

0
 
BadotzCommented:
I don't understand why "window.setTimeout" doesn't do what you want. Visit http://www.devguru.com/Technologies/ecmascript/quickref/win_settimeout.html for a brief example.
0
 
Viking46Author Commented:
Hi Onthrax,

Thank you for the function. A question,

var future = new Future();

What is the class Future? And what is .fulfill?

And to you Badotz, please see the following code. You can see this code in action at:

http://webappella.com/Samlaget/dice.html

Your advice would be much appreciated.
//function in html document
function throwD(){
	
		var dice1Id = document.getElementById('dice1');
		
		var terning = new dice('1', dice1Id, "Classes/graphics/singleDice3D.gif", "Classes/graphics/dice1.gif", "Classes/graphics/dice2.gif", "Classes/graphics/dice3.gif", "Classes/graphics/dice4.gif", "Classes/graphics/dice5.gif", "Classes/graphics/dice6.gif", "Classes/graphics/animatedDice.gif",flshProxy, "Classes/sounds/dice.mp3", "", "");
		
		var result = terning.throwDice();
		
	}
 
which calls the following class
 
//class constructor
function dice(numOfDice, img1Id, dice1ImgMain, diceImg1, diceImg2, diceImg3, diceImg4, diceImg5, diceImg6, animatedDice, flashProxy, diceSound, img2Id, dice2ImgMain)
{
 
	this.numOfDice = parseInt(numOfDice);
	this.dice1ImgMain = dice1ImgMain;
 
	if (diceSound == "" || diceSound === undefined) diceSound = "none";
	
	this.diceSound = diceSound;
 
	//check the supplied variables
	if (isNaN(numOfDice) || numOfDice > 2 || numOfDice < 1) {
		alert('Invalid number of dice provided!');
		return false;
		
	}
	
	if(img1Id == null){
		alert('Invalid HTML element provided for the first image!');
		return false;
	
	}else {this.img1Id = img1Id}
 
	//if there are 2 dice make sure that the parameters are valid
	if (this.numOfDice == 2)
	{
		if(img2Id == null)
		{
			alert('Invalid HTML element provided for the 2nd image!');
			return false;
		
		}//end if
		
		this.img2Id = img2Id;
		
		if (dice2ImgMain == undefined) this.dice2ImgMain = dice1ImgMain;
		
	}//end if
	
	if (diceImg1 == undefined || diceImg2 == undefined || diceImg3 == undefined || diceImg4 == undefined || diceImg5 == undefined || diceImg6 == undefined)
	{
		alert('You must provide an image for all 6 dice faces!')
		return false;
	}else
	{
		this.diceImg1 = diceImg1;
		this.diceImg2 = diceImg2;
		this.diceImg3 = diceImg3;
		this.diceImg4 = diceImg4;
		this.diceImg5 = diceImg5;
		this.diceImg6 = diceImg6;
		this.animatedDice = animatedDice;
		
	}
	this.flashProxy = flashProxy;
	this.throwDice = throwDice;
	this.diceResult = 1; //default value
	this.counter = 0; //counter var
	this.timer;//timer var
	this.randomnumber = 0; //random nr for timer
	this.setDiceFace = setDiceFace;
	
	return true;
}
 
	
	/* 
	function: throwDice()
	
	called by a client application when it is ready to throw
	one or more dice. It generates a random number, sets a graphic
	then returns the result of the dice roll.
 
	*/
	function throwDice()
	{
		
		var randomnumber=Math.floor(Math.random()*(this.numOfDice * 6 + 1));
		if (randomnumber == 0) randomnumber = 1;
		
		this.diceResult = randomnumber;
		
		this.img1Id.src = this.animatedDice;
		//here I play a sound (dice rolling)
		startStream (this.diceSound, this.flashProxy);
                
                /*
                 here I need to pause execution to allow the
                 graphic to show and the sound to finish
                 before showing the final dice face
                */ 
 
		this.setDiceFace(this.diceResult);
		
                /*
                   if no pause is in place the following return
                   happens before the final dice face is displayed
                */		
		return this.diceResult;
 
	}//end throw dice
	
 
	function setDiceFace(number)
	{
		switch (number)
		{
			case 1:
				this.img1Id.src = this.diceImg1;	
				break;
			case 2:
				this.img1Id.src = this.diceImg2;	
				break;
			case 3:
				this.img1Id.src = this.diceImg3;	
				break;
			case 4:
				this.img1Id.src = this.diceImg4;	
				break;
			case 5:
				this.img1Id.src = this.diceImg5;	
				break;
			case 6:
				this.img1Id.src = this.diceImg6;	
				break;
			default:
				//do nothing here
		}
 
	}
	
		/*
		function: audioFinished
		
		audioFinishedis fired by the built-in flash player 
		when an audio clip has finished playing
	*/
	function audioFinished(){
		
 
	}//end audiofinished
	

Open in new window

0
 
VoxEchoCommented:
seems to me that what you need to do is some event handling. as you will see in the attached code... if you don't respond to the return, but rather a callback event, you will not have to worry about timing so much.
//function in html document
function throwD(){
	
		var dice1Id = document.getElementById('dice1');
		
		var terning = new dice('1', dice1Id, "Classes/graphics/singleDice3D.gif", "Classes/graphics/dice1.gif", "Classes/graphics/dice2.gif", "Classes/graphics/dice3.gif", "Classes/graphics/dice4.gif", "Classes/graphics/dice5.gif", "Classes/graphics/dice6.gif", "Classes/graphics/animatedDice.gif",flshProxy, "Classes/sounds/dice.mp3", "", "");
		/** FIRST ADD AN EVENT HERE
		**/
		terning.onDiceThrow = function(value){
			/** DO WHATEVER IT WAS YOU WANTED TO DO WITH RESULT HERE
			**/
			var result = value;
		}	
	}
 
 
//class constructor
function dice(numOfDice, img1Id, dice1ImgMain, diceImg1, diceImg2, diceImg3, diceImg4, diceImg5, diceImg6, animatedDice, flashProxy, diceSound, img2Id, dice2ImgMain)
{
 
 	/** CREATE AN EMPTY FUNCTION TO ACT AS THE EVENT HANDLER
 	**/
 	this._onDiceThrow = function(s){
		/** ANY CODE YOU WANT TO HAPPEN BEFORE SENDING THE RETURN
		* VALUE BACK TO THE CALLING SCRIPT
		*/
		/** CALL THE EVENT HANDLER OUTSIDE THE CLASS
		**/
		this.onDiceThrow(s);
	};
 
	this.numOfDice = parseInt(numOfDice);
	this.dice1ImgMain = dice1ImgMain;
 
	if (diceSound == "" || diceSound === undefined) diceSound = "none";
	
	this.diceSound = diceSound;
 
	//check the supplied variables
	if (isNaN(numOfDice) || numOfDice > 2 || numOfDice < 1) {
		alert('Invalid number of dice provided!');
		return false;
		
	}
	
	if(img1Id == null){
		alert('Invalid HTML element provided for the first image!');
		return false;
	
	}else {this.img1Id = img1Id}
 
	//if there are 2 dice make sure that the parameters are valid
	if (this.numOfDice == 2)
	{
		if(img2Id == null)
		{
			alert('Invalid HTML element provided for the 2nd image!');
			return false;
		
		}//end if
		
		this.img2Id = img2Id;
		
		if (dice2ImgMain == undefined) this.dice2ImgMain = dice1ImgMain;
		
	}//end if
	
	if (diceImg1 == undefined || diceImg2 == undefined || diceImg3 == undefined || diceImg4 == undefined || diceImg5 == undefined || diceImg6 == undefined)
	{
		alert('You must provide an image for all 6 dice faces!')
		return false;
	}else
	{
		this.diceImg1 = diceImg1;
		this.diceImg2 = diceImg2;
		this.diceImg3 = diceImg3;
		this.diceImg4 = diceImg4;
		this.diceImg5 = diceImg5;
		this.diceImg6 = diceImg6;
		this.animatedDice = animatedDice;
		
	}
	this.flashProxy = flashProxy;
	this.throwDice = throwDice;
	this.diceResult = 1; //default value
	this.counter = 0; //counter var
	this.timer;//timer var
	this.randomnumber = 0; //random nr for timer
	this.setDiceFace = setDiceFace;
	
	return true;
}
 
	
	/* 
	function: throwDice()
	
	called by a client application when it is ready to throw
	one or more dice. It generates a random number, sets a graphic
	then returns the result of the dice roll.
 
	*/
	function throwDice()
	{
		
		var randomnumber=Math.floor(Math.random()*(this.numOfDice * 6 + 1));
		if (randomnumber == 0) randomnumber = 1;
		
		this.diceResult = randomnumber;
		
		this.img1Id.src = this.animatedDice;
		//here I play a sound (dice rolling)
		startStream (this.diceSound, this.flashProxy);
                
                /*
                 here I need to pause execution to allow the
                 graphic to show and the sound to finish
                 before showing the final dice face
                */ 
       /** MAKE A TARGER VARIABLE TO HELP WITH 
       * ADDRESSING THE CLASS FROM THE TIMEOUT EVENT
       */
       var target = this;
       /** SET TIMEOUT TO PAUSE
       **/
       var timeoutid = setTimeout(function(){
			 /** CLEAN UP THE TIMEOUT. 
			 */
			 clearTimeout(timeoutid);
			 /** USING TARGET SO THAT CALL IS MADE FROM THE
			 * CLASS LEVEL AND NOT THIS EVENT LEVEL, CALL THE
			 * CLASS EVENT HANDLER AND PASS IT THE
			 * NEW VALUE
			 */
			target._onDiceThrow(randomnumber);	 
		 }, 2000);
 
		
		
                /*
                   if no pause is in place the following return
                   happens before the final dice face is displayed
                */		
       /** REMOVE THE RETURN VALUE AS THIS FUNCTIONS
       * IS NOW EVENT DRIVEN
       */ // return this.diceResult;
 
	}//end throw dice
	
 
	function setDiceFace(number)
	{
		switch (number)
		{
			case 1:
				this.img1Id.src = this.diceImg1;	
				break;
			case 2:
				this.img1Id.src = this.diceImg2;	
				break;
			case 3:
				this.img1Id.src = this.diceImg3;	
				break;
			case 4:
				this.img1Id.src = this.diceImg4;	
				break;
			case 5:
				this.img1Id.src = this.diceImg5;	
				break;
			case 6:
				this.img1Id.src = this.diceImg6;	
				break;
			default:
				//do nothing here
		}
 
	}
	
		/*
		function: audioFinished
		
		audioFinishedis fired by the built-in flash player 
		when an audio clip has finished playing
	*/
	function audioFinished(){
		
 
	}//end audiofinished

Open in new window

0
 
daveamourCommented:
If you really do just want to pause for say 2 seconds rather than using timeOut then just have a loop which has a reference to the current time defined just before the loop and make the look keep checking if the new current time is 2 seconds or more than the old current time then exit the loop.
This is not good practice though but should do what you want.
0
 
BadotzCommented:
>>This is not good practice though but should do what you want.

Then why suggest it?
0
 
daveamourCommented:
I suggested it because the asker seemed determined to not use window.SetTimeout and refactor his code.
0
 
OnthraxCommented:
Whoops not the right code. Copy-pasted to fast. You should go with daveamour's solution.

Here's the code you will require

function pause(milliseconds) {
	var dt = new Date();
	while ((new Date()) - dt <= milliseconds) { /* Do nothing */ }
}

Open in new window

0
 
BadotzCommented:
>>Here's the code you will require

Right - thread-blocking is NEVER the proper course...sheesh...
0
 
Viking46Author Commented:
Gentelmen,

Thank you for the discussion and the result you all have lead towards. I would like to conclude this solution by saying that when I woke up this morning, I had solved the problem. I would like to make the following comments to those two have tried to help me:

Voxecho - although I haven't tested your solution, yours is the closest to mine. Of course an event needs to be raised when the class is ready to produce its result. If I implemented a timer in your solution it would undoubtedly work. I solved the problem by letting the media player raise an event when it had finished streaming the sound of the dice roll. This negated the need for using a timer. Thank you for the work you put into creating a solution.

Bardotz - you are quite correct to point out that the blocking of the thread is never a good idea; even though the sound file would only be for a very short period of time it should not be allowed to freeze the class and therefore the webpage. Thank you for your input.

Onthrax and daveamour - even know it was agreed that a timeout is the incorrect course of action you both provided solutions (again I'm tested by me) to the timing problem. Thank you both for your input.

I have awarded points accordingly.

Thank you all for your assistance.
0
 
BadotzCommented:
>>I would like to conclude this solution by saying that when I woke up this morning, I had solved the problem.

Please tell us how.
0
 
Viking46Author Commented:
Yes of course. See my code below...
//code used in html document
	var terning;
	
	function throwD(){
	
		var dice1Id = document.getElementById('dice1');
		
		terning = new dice('1', dice1Id, "Classes/graphics/singleDice3D.gif", "Classes/graphics/dice1.gif", "Classes/graphics/dice2.gif", "Classes/graphics/dice3.gif", "Classes/graphics/dice4.gif", "Classes/graphics/dice5.gif", "Classes/graphics/dice6.gif", "Classes/graphics/animatedDice.gif",flshProxy, "Classes/sounds/dice.mp3", "", "");
		
		terning.throwDice();
		
	}
	
	/*
		function: audioFinished
		
		audioFinishedis fired by the built-in flash player 
		when an audio clip has finished playing
	*/
	function audioFinished(){
		var result = terning.getResult();
		
		alert('You threw a ' + result);
 
	}//end audiofinished
 
//dice class code
/* 
	function: dice
	
	the instructor for the dice class
	
	Parameters:
	
		int - numOfDice. The number of dice to use
		string - img1ID. The id of the html img element for dice 1
		string - dice1ImgMain. The location of the 1 dice img.
		string - diceImg1. Location of the image for 1 dot
		string - diceImg2. Location of the image for 2 dots
		string - diceImg3. Location of the image for 3 dots
		string - diceImg4. Location of the image for 4 dots
		string - diceImg5. Location of the image for 5 dots
		string - diceImg6. Location of the image for 6 dots
		string - diceSound. Optional Location of mp3 file of rolling dice
		string - img2ID. Optional The id of the html img element for dice 2
		string - dice2ImgMain. Optional: The location of the 2 dice img. If ommtted and 2 dice are specified in paramet 2, The first image will be reused.
	
*/
function dice(numOfDice, img1Id, dice1ImgMain, diceImg1, diceImg2, diceImg3, diceImg4, diceImg5, diceImg6, animatedDice, flashProxy, diceSound, img2Id, dice2ImgMain)
{
 
	this.numOfDice = parseInt(numOfDice);
	this.dice1ImgMain = dice1ImgMain;
 
	if (diceSound == "" || diceSound === undefined) diceSound = "none";
	
	this.diceSound = diceSound;
 
	//check the supplied variables
	if (isNaN(numOfDice) || numOfDice > 2 || numOfDice < 1) {
		alert('Invalid number of dice provided!');
		return false;
		
	}
	
	if(img1Id == null){
		alert('Invalid HTML element provided for the first image!');
		return false;
	
	}else {this.img1Id = img1Id}
 
	//if there are 2 dice make sure that the parameters are valid
	if (this.numOfDice == 2)
	{
		if(img2Id == null)
		{
			alert('Invalid HTML element provided for the 2nd image!');
			return false;
		
		}//end if
		
		this.img2Id = img2Id;
		
		if (dice2ImgMain == undefined) this.dice2ImgMain = dice1ImgMain;
		
	}//end if
	
	if (diceImg1 == undefined || diceImg2 == undefined || diceImg3 == undefined || diceImg4 == undefined || diceImg5 == undefined || diceImg6 == undefined)
	{
		alert('You must provide an image for all 6 dice faces!')
		return false;
	}else
	{
		this.diceImg1 = diceImg1;
		this.diceImg2 = diceImg2;
		this.diceImg3 = diceImg3;
		this.diceImg4 = diceImg4;
		this.diceImg5 = diceImg5;
		this.diceImg6 = diceImg6;
		this.animatedDice = animatedDice;
		
	}
	this.flashProxy = flashProxy;
	this.diceResult = 1; //default value
	this.counter = 0; //counter var
	this.timer;//timer var
	this.randomnumber = 0; //random nr for timer
	
	//functions
	this.changeDiceFace = changeDiceFace;
	this.throwDice = throwDice;
	this.getResult = getResult;
	
	return true;
}
 
	function getResult()
	{
		this.changeDiceFace(this.diceResult);
		return this.diceResult;
	}
 
	
	/* 
	function: throwDice()
	
	called by a client application when it is ready to throw
	one or more dice. It generates a random number, sets a graphic
	then returns the result of the dice roll.
 
	*/
	function throwDice()
	{
		
		/*by generating a random number specifying this.numOfDice *6+1
		will ensure that the random number generated lies between the
		value of 1 and the maximum number of the dots available
		on the specified number of guides
		*/
		var randomnumber=Math.floor(Math.random()*(this.numOfDice * 6 + 1));
		if (randomnumber == 0) randomnumber = 1;
		
		this.diceResult = randomnumber;
		
		this.img1Id.src = this.animatedDice;
		startStream (this.diceSound, this.flashProxy);
		
		return true;
 
	}//end throw dice
	
 
	function changeDiceFace(number)
	{
		switch (number)
		{
			case 1:
				this.img1Id.src = this.diceImg1;	
				break;
			case 2:
				this.img1Id.src = this.diceImg2;	
				break;
			case 3:
				this.img1Id.src = this.diceImg3;	
				break;
			case 4:
				this.img1Id.src = this.diceImg4;	
				break;
			case 5:
				this.img1Id.src = this.diceImg5;	
				break;
			case 6:
				this.img1Id.src = this.diceImg6;	
				break;
			default:
				//do nothing here
		}
 
	}
	
	
	/*
		function: startStream
		
		startStreamis used to instruct the embedded Flash 
		player to start streaming the current audio clip
		
		Parameters:
		
			string - fileName. Name of the file to stream
			object - flProxy. Reference to the flash proxy object
	*/
	function startStream(fileName, flProxy){
		try{
			flProxy.call('audioPlay', fileName);
 
		}catch(err){}
	}

Open in new window

0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

  • 4
  • 4
  • 4
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now