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/
精彩评论