Sheri Trager
Sheri Trager

Reputation: 852

Using JQuery Deferred and Promise

I have a function that I want to use deferred and promise to chain an animation.

The first animation is a type writer plugin, using https://github.com/stephband/jticker/blob/master/js/jquery.jticker.js. The second is a function that contains other animations.

What I want to do is run the first animation and when the animation is completed, run the second.

 $(function () {            
        var ticker =setTimeout(runTicker(), 8000);           
        $.when(ticker).done(function(){
            setTimeout(Other(),16000)});
    });

  function runTicker() {
        $("#ticker").ticker({
            cursorList: " ",
            rate: 50,
            delay: 18000
        }).trigger("play").trigger("stop");
    }

I have tried numerous examples of deferred, but still can't get it.

I finally cleared all the examples in order to get the ticker working again.

How would I use deferred and promise to run the Other() function?

Thank you

Upvotes: 1

Views: 740

Answers (2)

Bergi
Bergi

Reputation: 664297

Don't know how to solve your actual problem with a proper callback-based solution (not enough information on the Ticker plugin you use), but I can explain what goes wrong in your current code:

var ticker = setTimeout(runTicker(), 8000);

Don't call runTicker immediately. What you want is to pass the function itself - not the result of its invocation - into setTimeout. A [plain integer] number will be returned and is assigned to ticker. It can be used for identifying the timeout when aborting it via clearTimeout - and nowhere else.

$.when(ticker)...

creates a new Deferred now. Have a look at its documentation: It will combine Deferred objects with each other and create immediately-resolved Promises for any other values - like numbers. Therefore, your done callback is also called immidiately, and again you make the mistake with executing Other instead of passing it into setTimeout.


As the plugin you used seems very limited in regard to callbacks, I've written my own now (just for fun :-). It adapts my solution from this former answer which uses pure DOM methods quite elegantly. It is written as a standard jQuery plugin, even favours stop and go methods and - most important - integrates well in the jQuery fx queue. That means you will be able to use it exactly like animate() regarding callbacks and chaining, and if you want to work with Deferreds you can invoke the promise() method to get a Promise for the queue's end. Example call:

$('#ticker').fadeOut().delay(2000).typewriter({framerate:1000/30}, function() {
    // the typewriter effect has just ended
}). ... .promise().done(function() {
    // effect queue has ended - start Other()
});

jQuery(".stop").click($.fn.typewriter.bind($("#ticker"), "stop"));

Code at jsfiddle.net

Upvotes: 1

jAndy
jAndy

Reputation: 235972

setTimeout obviously will not return a jQuery Deferred object, its a native Javascript method here. You need to re-write it like so:

function runTicker() {
    return jQuery.Deferred(function( promise ) {
        setTimeout(function() {
            $("#ticker").ticker({
                cursorList: " ",
                rate: 50,
                delay: 18000
            }).trigger("play").trigger("stop");

            promise.resolve();
        }, 8000);
    }).promise();
}

And then you can call it like

var ticker = runTicker();

jQuery.when( ticker ).done(function() {
    setTimeout(Other,16000)});
});

Upvotes: 0

Related Questions