*注:重写问题:
我正在尝试在单个函数调用之外编写以下内容:
例子:
函数 f1(){ 做某事1 } 函数 f2(){ 做某事2 } 运行功能 1 完成后 运行功能 2
(有关 jsfiddles,请参阅下面的评论)
问题是,盒子是同时加载的。行为应该是,加载红色,完成后加载绿色。
如果这不是jQuery中常用的方法,请告诉我,也许我只是在追鬼……
取决于功能。
对于同步函数:只需一个接一个地调用它们。
对于异步函数:取决于使其异步的原因。
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
,并且您不希望篡改这些功能。如果是这种情况,我只能想到一个解决方案:从正在制作动画的元素中获取一个Promise 对象firstFunction
,然后定义secondFunction
为成功处理程序:
firstFunction();
$('.one').promise().then(secondFunction);
promise()
返回一个绑定到该元素当前动画状态的 Promise 对象。$('.one').promise().then(secondFunction)
本质上是在说“我保证secondFunction
在当前动画.one
完成后运行。
如果你愿意篡改现有的函数,你也可以作为 inside 的回调参数调用,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);
延期是一种选择。您始终可以执行以下操作:
$.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。
您可以简单地在第一个函数的末尾调用第二个函数。
$(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
小提琴
你可以使用 jquery Callbacks 函数,从 v1.7up
var callbacks = $.Callbacks();
callbacks.add( firstFunction );
callbacks.add( secondFunction );
callbacks.fire( );
代替
firstFunction(function(){
secondFunction();
});
写
firstFunction();
secondFunction();
我最近遇到了这个问题。如果您有一堆执行异步操作的函数,只需将它们全部返回一个 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);