msqar msqar - 7 months ago 21
Javascript Question

jQuery Promises with chained setTimeouts

I'm doing a little dice game to learn.
What I do is i scrumble the dice X amount of times, keep slowing the random down until it gets to the final value, and that's the "winning number".

But i would like to execute the scrumble 1 by 1 on the dices. Imagine I got 2. And later I do a little zoom effect.
I was thinking I could achieve this by using promises but is not working for me, I don't know what I'm missing.

Here's the JS code:

var counter = 0.8;
var diceNumber = 0;

var rollDice = function(diceId){
var dfd = new $.Deferred();

$('#' + diceId).removeClass('idle');

counter *= 1.2;

diceNumber = Math.round(Math.random()*5) + 1;

$('#' + diceId).removeClass();
$('#' + diceId).addClass('dice_' + diceNumber);

if(counter < 800) {
timeout = setTimeout(rollDice, counter, diceId);
}else{
$('.winner').text(diceNumber);
$('#' + diceId).removeClass();
$('#' + diceId).addClass('animate');
$('#' + diceId).addClass('dice_' + diceNumber)
.animate({ zoom: '1.3' }, 200)
.animate({ zoom: '1' }, 100);

dfd.resolve();

return dfd.promise();
}
}


var startToDice = function() {
rollDice('dice_1').then(rollDice('dice_2'));
}

startToDice();


And what it ends up doing is running both dices simultaneously.

Any advice? Thanks.

Answer

You're on the right track. I couldn't test cause I don't have all the elements in place, but try this out:

var counter = 0.8;
var diceNumber = 0;

var rollDice = function(diceId){
    var dfd = new $.Deferred();

    var roll = function() {
        $('#' + diceId).removeClass('idle');

        counter *= 1.2;

        diceNumber = Math.round(Math.random()*5) + 1;

        $('#' + diceId).removeClass();
        $('#' + diceId).addClass('dice_' + diceNumber);

        if(counter < 800) {
            timeout = setTimeout(roll, counter);
        }else{
            $('.winner').text(diceNumber);
            $('#' + diceId).removeClass();
            $('#' + diceId).addClass('animate');
            $('#' + diceId).addClass('dice_' + diceNumber)
            .animate({ zoom: '1.3' }, 200)
            .animate({ zoom: '1' }, 100);

            dfd.resolve();
        } 
    }

    roll();

    return dfd.promise();
}


var startToDice = function() {
    rollDice('dice_1').then(function(){
         rollDice('dice_2');
    });
}

startToDice();

Let me know if you get any errors when you run it so I can make adjustments as necessary.