6

*注:重写问题:

我正在尝试在单个函数调用之外编写以下内容:

例子:

函数 f1(){
    做某事1
}
函数 f2(){
    做某事2   
}

运行功能 1
完成后
运行功能 2

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

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

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

4

6 回答 6

14

取决于功能。

简短的回答:

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

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

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

jsFiddle

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

如果你愿意篡改现有的函数,你也可以作为 inside 的回调参数调用,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

于 2013-01-20T10:57:37.503 回答
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。

于 2013-01-20T02:22:28.530 回答
4

您可以简单地在第一个函数的末尾调用第二个函数。

 $(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 小提琴

于 2013-01-19T07:14:18.353 回答
4

你可以使用 jquery Callbacks 函数,从 v1.7up

var callbacks = $.Callbacks();
callbacks.add( firstFunction );
callbacks.add( secondFunction );
callbacks.fire( );
于 2013-01-19T07:29:20.127 回答
1

代替

 firstFunction(function(){
        secondFunction();
    });

firstFunction();
secondFunction();
于 2013-01-19T07:14:03.970 回答
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);
于 2018-07-10T10:25:26.887 回答