jquery,如何在另一个函数结束时运行一个函数

时间:2013-01-19 07:11:19

标签: jquery function

*注意:重写问题:

我正在尝试编写以下外部的各个函数调用:

示例:

function f1(){
    do something 1
}
function f2(){
    do something 2   
}

run function 1
when done
run function 2

(请参阅以下有关jsfiddles的评论)

问题是,盒子同时加载。行为应该是,加载红色,完成后,加载绿色。

如果这不是jQuery中的常用方法,请告诉我,也许我只是在追逐鬼......

6 个答案:

答案 0 :(得分:11)

取决于功能。

简答:

对于同步功能:只需一个接一个地调用它们。

对于异步函数:取决于使它异步的原因。

jQuery动画?从动画的方法或fx队列的Promise对象定义回调参数。

setTimeout / setInterval /还有别的什么?最有可能的是,需要重写函数以提供回调或Deferred / Promise对象。

有关示例,请参阅thisthis

答案很长:

根据你评论中的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);

jsFiddle

promise()返回绑定到该元素当前动画状态的Promise对象。 $('.one').promise().then(secondFunction)基本上是说“我保证在完成secondFunction的当前动画时运行.one

如果您愿意篡改现有功能,也可以将secondFunction作为fadeOutfirstFunction的回调参数,但这不是一个非常优雅的解决方案。

如果您愿意重写函数,理想的解决方案是使用Deferreds和Promises来驯服您的异步函数。这是一个快速入门:

  • 在jQuery中,Deferred对象是一个特殊对象,可用于定义函数的成功/失败状态。你可以在你的功能中使用它。
  • Promise对象是一个特殊对象,可用于向这些成功/失败状态添加回调。你在功能之外使用它。

使用这些工具,您可以重写函数以指定它们何时“完成”,并且您可以在函数外部提供代码,以便知道它们何时完成(并在其执行之后执行)。

重写为使用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);

jsFiddle

如果所有函数都是以这种方式编写的,那么您可以控制它们的执行顺序并使用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);

jsFiddle

答案 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();
});

fiddle

或者,如果您不想在每次拨打第一个电话时拨打第二个电话,您可以直接拨打电话

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);