*注意:重写问题:
我正在尝试编写以下外部的各个函数调用:
示例:
function f1(){ do something 1 } function f2(){ do something 2 } run function 1 when done run function 2
(请参阅以下有关jsfiddles的评论)
问题是,盒子同时加载。行为应该是,加载红色,完成后,加载绿色。
如果这不是jQuery中的常用方法,请告诉我,也许我只是在追逐鬼......
答案 0 :(得分:11)
取决于功能。
对于同步功能:只需一个接一个地调用它们。
对于异步函数:取决于使它异步的原因。
jQuery动画?从动画的方法或fx队列的Promise对象定义回调参数。
setTimeout / setInterval /还有别的什么?最有可能的是,需要重写函数以提供回调或Deferred / Promise对象。
根据你评论中的jsFiddles,你有这两个功能:
function firstFunction(){
$(".one").fadeIn(1000).delay(2000).fadeOut();
}
function secondFunction(){
$(".two").fadeIn(1000).delay(2000).fadeOut();
}
您希望在secondFunction
之后运行firstFunction
,并且您不希望篡改这些功能。如果是这种情况,我只能想到一个解决方案:从firstFunction
动画的元素中获取Promise object,然后将secondFunction
定义为成功处理程序:
firstFunction();
$('.one').promise().then(secondFunction);
promise()
返回绑定到该元素当前动画状态的Promise对象。 $('.one').promise().then(secondFunction)
基本上是说“我保证在完成secondFunction
的当前动画时运行.one
。
如果您愿意篡改现有功能,也可以将secondFunction
作为fadeOut
内firstFunction
的回调参数,但这不是一个非常优雅的解决方案。
如果您愿意重写函数,理想的解决方案是使用Deferreds和Promises来驯服您的异步函数。这是一个快速入门:
使用这些工具,您可以重写函数以指定它们何时“完成”,并且您可以在函数外部提供代码,以便知道它们何时完成(并在其执行之后执行)。
重写为使用Deferred和Promise,代码如下所示:
function firstFunction(){
var deferred = $.Deferred();
$(".one").fadeIn(1000).delay(2000).fadeOut(function() {
deferred.resolve();
});
return deferred.promise();
}
function secondFunction(){
var deferred = $.Deferred();
$(".two").fadeIn(1000).delay(2000).fadeOut(function() {
deferred.resolve();
});
return deferred.promise();
}
firstFunction().then(secondFunction);
如果所有函数都是以这种方式编写的,那么您可以控制它们的执行顺序并使用then()
顺序运行它们。这是一个更全面的例子:
function one(){
var deferred = $.Deferred();
$(".one").fadeOut(500, function() {
$(this).appendTo('body').fadeIn(500, function() { deferred.resolve(); });
});
return deferred.promise();
}
function two(){
var deferred = $.Deferred();
$(".two").fadeOut(1500, function() {
$(this).appendTo('body').fadeIn(500, function() { deferred.resolve(); });
});
return deferred.promise();
}
function three(){
var deferred = $.Deferred();
$(".three").fadeOut(1000, function() {
$(this).appendTo('body').fadeIn(500, function() { deferred.resolve(); });
});
return deferred.promise();
}
function four(){
var deferred = $.Deferred();
$(".four").fadeOut(750, function() {
$(this).appendTo('body').fadeIn(500, function() { deferred.resolve(); });
});
return deferred.promise();
}
function five(){
var deferred = $.Deferred();
$(".five").fadeOut(600, function() {
$(this).appendTo('body').fadeIn(500, function() { deferred.resolve(); });
});
return deferred.promise();
}
one()
.then(two)
.then(three)
.then(four)
.then(five);
答案 1 :(得分:6)
延期是一种选择。您可以随时执行以下操作:
$.when(firstFunction()).then(secondFunction);
唯一的技巧是在firstFunction内部,您需要执行以下操作:
function firstFunction(){
var deferred = $.Deffered();
$.get(url,function(r){
deferred.resolve();
});
return deferred;
}
when函数将等待,直到firstFunction调用返回的deferred被解析。一旦延迟解决(在ajax成功回调中)'.then'语句将触发,调用你的secondFunction。
jQuery文档很好地解释了Deferred API。
答案 2 :(得分:5)
你可以简单地在第一个函数的末尾调用第二个函数。
$(document).ready(function() {
function firstFunction(){
alert("this is the first function!");
secondFunction();
}
function secondFunction(){
alert("this is the second function!");
}
firstFunction();
});
或者,如果您不想在每次拨打第一个电话时拨打第二个电话,您可以直接拨打电话
firstFunction();
secondFunction();
这是有效的,因为它会等到firstFunction
完成后再转移到secondFunction
fiddle
答案 3 :(得分:4)
你可以使用jquery Callbacks函数,来自v1.7up
var callbacks = $.Callbacks();
callbacks.add( firstFunction );
callbacks.add( secondFunction );
callbacks.fire( );
答案 4 :(得分:1)
而不是
firstFunction(function(){
secondFunction();
});
写
firstFunction();
secondFunction();
答案 5 :(得分:0)
我最近有这个问题。如果您有一堆执行异步工作的函数,只需使它们全部返回Deferred,就可以在函数异步作业完成时手动解决这些问题。然后,您可以将函数放入数组中并按顺序运行它们:
// Sample asynchronous function that returns Deferred
var f = function(name){
console.log('Function root start', name);
var d = $.Deferred();
d.done(function(result){
console.log('Async work finish', name, result);
});
setTimeout(function(){
setTimeout(function(){
d.resolve('Hello');
}, 200);
}, 1000);
console.log('Function root finish', name);
return d;
};
// Array with functions
var defs = [];
defs.push(f.bind(null, 1));
defs.push(f.bind(null, 2));
defs.push(f.bind(null, 3));
// Recursive sequential calling
var i = 0;
var runAtIndex = function (i) {
i < defs.length && defs[i]().done(function() { runAtIndex(i + 1); });
}
runAtIndex(i);