开发者

How can I call some javascript functions but, waiting for the previous has finished?

I want to call some functions but waiting for the previous one has finished. I know jQuery provides a callback argument in several functions, but I want to learn how implement this behaviour in my own jQuery plugin. So this is the case:

After read answers from my previous question I wrote this:

    (function(callback){
        $('#art1').animate({'width':'1000px'},1000);
        callback();
    })((function(callback2){
开发者_C百科        $('#art2').animate({'width':'1000px'},1000);
        callback2();
    })(function(){
        $('#art3').animate({'width':'1000px'},1000);
    }));

But not working. I've tried again and wrote this:

    animate1(function(){
        animate2(function(){
            animate3();
        })
    });

    function animate1(callback){
        $('#art1').animate({'width':'1000px'},1000);
        callback();
    }
    function animate2(callback){
        $('#art2').animate({'width':'1000px'},1000);
        callback();
    }
    function animate3(callback){
        $('#art3').animate({'width':'1000px'},1000);
        callback();
    }

But still not working. Three animates still starting at same time. I want they were called one after other. But without using:

    $('#art1').animate({'width':'1000px'},1000,'linear',function(){
        $('#art2').animate({'width':'1000px'},1000,'linear',function(){
            $('#art3').animate({'width':'1000px'},1000);        
        });        
    });  


That's what the Buffer is for:

var Buffer = function(handler) {
    var tasks = [];
    // empty resolved deferred object
    var deferred = $.when();

    // handle the next object
    function handleNextTask() {
        // if the current deferred task has resolved and there are more tasks
        if (deferred.isResolved() && tasks.length > 0) {
            // grab a task
            var task = tasks.shift();
            // set the deferred to be deferred returned from the handler
            deferred = handler(task);
            // if its not a deferred object then set it to be an empty deferred object
            if (!(deferred && deferred.promise)) {
                deferred = $.when();
            }
            // if we have tasks left then handle the next one when the current one 
            // is done.
            if (tasks.length > 0) {
                deferred.done(handleNextTask);
            }
        }
    }

    // appends a task.
    this.append = function(task) {
        // add to the array
        tasks.push(task);
        // handle the next task
        handleNextTask();
    };
};

Then we just create a task handler for the animation, an animation task and append the tasks to the buffer.

function handleAnimation(task) {
    var def = $.Deferred();
    $(task.id).animate(task.props, task.timeout, task.options function() {
        def.resolve();
    });
    return def.promise();
}

function AnimationTask(id, props, timeout, options) {
    this.id = id;
    this.props = props;
    this.timeout = timeout;
    this.options = options;
}

var buffer = new Buffer(handleAnimation);
buffer.append(new AnimationTask("#art1", {
    "width": "1000px"
}, 1000, "linear");
buffer.append(new AnimationTask("#art2", {
    "width": "1000px"
}, 1000, "linear");
buffer.append(new AnimationTask("#art3", {
    "width": "1000px"
}, 1000, "linear");

This uses the magic of jQuery deferred to run tasks one after the other. It's probably a lot easier to just chain them.

Also this would work:

(function(callback){
    $('#art1').animate({'width':'1000px'},1000, function() {
         callback();
    });
})((function(callback2){
    $('#art2').animate({'width':'1000px'},1000, function() {
         callback2();
    });
})(function(){
    $('#art3').animate({'width':'1000px'},1000);
}));


I recommend you Jquery Defered Object


Here's an example of using callbacks in your own jquery extension:

http://jquery-howto.blogspot.com/2009/11/create-callback-functions-for-your.html


You need to pass your callbacks as arguments to the calls to animate:

function Animate(afterFirst,afterSecond) {
  $('#art1').animate({'width':'1000px'},1000,function(afterFirst,afterSecond) {
    afterFirst();
    $('#art2').animate({'width':'1000px'},1000,function(afterSecond) {
      afterSecond();
      $('#art3').animate({'width':'1000px'},1000);
    });
  });
}


if you just want your animate to run one by one, you just need to set queue: true as one of the animate properties. http://api.jquery.com/animate/

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜