在JavaScript中编写相同深度回调的更好方法

时间:2014-01-24 18:48:12

标签: javascript callback

我正在编写一段代码,使得一个HTML元素使用一个带有animate(params, delay, easing, callback)签名的函数(来自RaphaelJS)闪烁三次。我们的想法是callback在动画结束后delay毫秒后执行。所以我有以下代码:

var theElement = anElement;

function animateOpacity(newOpacity, callback) {
    theElement.animate({ opacity: newOpacity }, 500, null, callback);
}

function blink() {
    animateOpacity(0.1, function() {
        animateOpacity(1, function() {
            animateOpacity(0.1, function() {
                animateOpacity(1, function() {
                    animateOpacity(0.1, function() {
                        theElement.remove();
                    });
                });
             });
         });
     });
  }

......看起来很可怕。有没有人知道在没有所有这些嵌套匿名函数的情况下将这个animateOpacity函数称为回调函数的更好方法?感谢。

8 个答案:

答案 0 :(得分:2)

我改变了你的代码(这就是我所说的回调循环):

function blink() {
    var opacities = [0.1, 1, 0.1, 1, 0.1];
    animate(opacities, 0);
}

function animate(arr, i) {
    if (i == arr.length) {
        theElement.remove();
        return;
    }
    animateOpacity(arr[i], function () {
        animate(arr, i++);
    });
}

答案 1 :(得分:1)

您可以使用公共代码和计数器:

function blink(theElement, numBlinks) {

    var lastOpacity = 0.1;

    function animateOpacity(newOpacity, callback) {
        theElement.animate({ opacity: newOpacity }, 500, null, callback);
    }

    function next() {
        --numBlinks;
        if (numBlinks > 0) {
            lastOpacity = lastOpacity < 1 ? 1: 0.1;
            animateOpacity(lastOpacity, next);
        } else {
            theElement.remove();
        }
    }

    animateOpacity(0.1, next);

}

答案 2 :(得分:1)

我会在几个名为conditionnally的回调中爆炸它:

var theElement = anElement,
    blinksRemaining = 3;

function animateOpacity(newOpacity, callback) {
    theElement.animate({ opacity: newOpacity }, 500, null, callback);
}
function removeElement() {
    theElement.remove();
}

function fadeOutThenIn() {
    blinksRemaining--;
    animateOpacity(0.1, blink);
}

function blink() {
    animateOpacity(1, blinksRemaining ? fadeOutThenIn : removeElement);
}

blink();

答案 3 :(得分:1)

未经测试,但我认为以下情况应该有效:

var theElement = anElement;

function animateOpacity(newOpacity, callback) {
    theElement.animate({ opacity: newOpacity }, 500, null, callback);
}

function blink() {
    var args = [0.1, 1, 0.1, 1, 0.1];
    var func = function() {
        theElement.remove();
    };
    for (var i = args.length - 1; i >= 0; i--) {
        func = animateOpacity.bind(null, args[i], func);
    }
    func();
}

这里的想法是从内到外创建函数,将内部函数作为参数绑定到新外部函数以及每一步中的另一个参数。

答案 4 :(得分:0)

结帐jQuery deferredtutorial)。但是也有other个库提供了这项功能。

当然你也可以这样做(未经测试):

function blink(opacity, count) {
    opacity = opacity === .1 ? 1 : .1;
    if(count < 3) {
        animateOpacity(opacity, blink.bind(null, opacity, ++count));
    }
}
blink(1, 0);

答案 5 :(得分:0)

您可以使用setInterval()或setTimeout()函数

http://www.w3schools.com/js/js_timing.asp

更清洁的方式

使用条件检查三次

答案 6 :(得分:0)

一种可能性是使用间隔

的conttolling函数
function blinkingBlinker(newOpacity, callback){
    var blink_count = 0;
    var blink = setInterval(animateOpacity,1000);

    function animateOpacity(){
        blink_count++;

       function animateOpacity() {
          theElement.animate({ opacity: newOpacity }, 500, null, callback);
          }

        if (blink_count==3){
            clearInterval(blink)
        }
    }}

因此,您调用blinkingBlinker函数并在内部每秒运行animateOpacity,直到闪烁次数超过您想要的闪烁次数。

答案 7 :(得分:0)

可以使用以下css模仿眨眼效果

    @-webkit-keyframes blinker { from {opacity:1.0;} to {opacity:0.1;} }
    @keyframes blinker { from {opacity:1.0;} to {opacity:0.1;} }
    #element{

        text-decoration:blink;
        -webkit-animation-name:blinker;
        animation-name:blinker;
        -webkit-animation-iteration-count:10;
        animation-iteration-count:10;
        -webkit-animation-timing-function:cubic-bezier(1.0,0,0,1.0);
        animation-timing-function:cubic-bezier(1.0,0,0,1.0);
        -webkit-animation-duration:0.5s;
        animation-duration:0.5s; 
     }