2017-03-16 41 views
0

小提琴:https://jsfiddle.net/x89ja8r8/递延()只能使2个功能异步

我一直在寻找周围找到一个快速的方法来链功能异步。 Stackoverflow提供了很多“相同”的解决方案,但是当我尝试它时,总会有一些错误。

在下面的例子中,我有3个函数。我尝试使用$ .Deffer()异步链接它们。

期望:股利将动画改变其尺寸为5500ms的持续时间,然后股利会褪色至0.25透明度在2000毫秒的时间,然后在div的innerHTML将变为DONE!

结果:在div改变其的innerHTML(从FN3())同时其改变其尺寸(从FN1())为5500ms的持续时间,然后它消失至0.25不透明度在持续时间2000ms(来自fn2())。

function fn1() { 

    $("#result").animate({ 
    width: 800, 
    height: 800 
    }, 5500); 

} 

function fn2() { 

    $("#result").animate({ 
    opacity: 0.25 
    }, 2000); 

} 

function fn3() { 

    $("#result").html("DONE!"); 

} 

var dfr = $.Deferred(); 

dfr.done(fn1, fn2, fn3).resolve(); 

这里有什么问题?如果根本不起作用,那么fn1()和fn2()之间就不应该有异步。结果清楚地表明,fn2()确实等待fn1()完成,但是fn3()只是在没有等待的情况下开始执行。

+0

这两个按顺序运行的函数是这样做的,因为'.animate()'具有等待所有其他动画在开始之前完成的特殊行为。 – 4castle

回答

0

dfr.done(fn1,fn2,fn3)将同时执行所有功能,而不是按顺序执行。由于$ .animate()是一个异步操作,根据jQuery的文档,它可以接受一个将在动画完成时调用的回调函数,也可以让它返回一个promise。然后,你将不得不使用链$ .Deferred.then()的承诺,像这样:

$(document).ready(function() { 
 
    function fn1() { 
 
    return $("#result").animate({ 
 
     width: 800, 
 
     height: 800 
 
    }, 5500).promise(); 
 
    } 
 

 
    function fn2() { 
 
    return $("#result").animate({ 
 
     opacity: 0.25 
 
    }, 2000).promise(); 
 
    } 
 

 
    function fn3() { 
 
    return $("#result").html("DONE!").delay(2000).promise(); 
 
    } 
 

 
    function fn4() { 
 
    var fn4Dfr = $.Deferred(); 
 
    setTimeout(function() { 
 
     $("#result").html("Okay!"); 
 
     fn4Dfr.resolve(); 
 
    }, 2000); 
 
    return fn4Dfr; 
 
    } 
 

 
    var dfr = $.Deferred(); 
 
    dfr.then(fn1).then(fn2).then(fn3).then(fn4); 
 
    dfr.resolve(); 
 
});

fn3的使用延迟,其行为类似于setTimeout的,和FN4使用setTimeout的,所以我们创建一个我们可以根据需要解决的承诺(并立即返回承诺)。

+0

嗨,宝。感谢您的答复。现在我知道$ .animate()本身是异步的,如果我有另一个不是异步函数的fn4(),会发生什么?那么我如何链接它们,因为我在这里尝试了https://jsfiddle.net/x89ja8r8/并且它没有按预期工作。 – user3622260

+0

我包含了一个使用$ .delay()的例子,它在fn3中有一个承诺。对于fn4,如果您决定执行没有承诺的事情,那么您可以创建一个并在完成时解决。 https://jsfiddle.net/52fvv0xw/ – baohouse

+0

因此,给定一个纯JavaScript函数fn(){/ *代码在这里* /},有没有什么办法让该函数的承诺woth jQuery? – user3622260

0

对于这种特殊的使用情况,您可以使用一个简单的回调,而不是$.Deferred

$("#result") 
 
.animate({ width: 800, height: 800 }, 5500) 
 
.animate({ opacity: 0.25 }, 2000, function() { 
 
    $(this).text('Done!') 
 
})
div { 
 
    width: 100px; 
 
    height: 100px; 
 
    background-color: #ccc; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="result">Result</div>

+0

嗨。谢谢你的建议。但是,我需要Deferred(),因为我需要链接函数()(纯JavaScript),它们本身可能不是异步函数。如果你有4个函数,你将如何异步执行它们? – user3622260

+0

嗨。我在这里尝试过https://jsfiddle.net/x89ja8r8/1/,但它没有按预期工作。 – user3622260

+0

应该在这里修复:https://jsfiddle.net/x89ja8r8/2/ – gyre

0

我一直在寻找周围找到一个快速的方法来链功能异步。

done method不会链任何东西。它安装处理程序来运行,如果你传递了多个参数,它将同时调用函数。永远不要使用done

您正在寻找的是承诺的then method,它返回一个新的承诺,这将与回调的结果(等待它返回另一个承诺时)解决。其实你根本不需要延期!

function fn1() { 
    return $("#result").animate({ 
    width: 800, 
    height: 800 
    }, 5500).promise(); 
} 
function fn2() { 
    return $("#result").animate({ 
    opacity: 0.25 
    }, 2000).promise(); 
} 
function fn3() { 
    $("#result").html("DONE!"); 
} 

fn1().then(fn2).then(fn2);