jQuery 延迟 - 当多个超时任务完成时

jQuery deferred - when multiple timeout tasks have completed

在使用 $.deferred$.when$.done 时遇到一些初期问题。

我正在调用一个方法,该方法在计时器上有几个任务。当此方法中的所有内容(包括计时器中的内容)完成时,我正在寻找回调,因此开始查看 $.when()$.done() 以实现此目的。

我遇到的问题是函数在任务完成之前触发,在调用方法时立即触发。所以,我开始使用 $.deferredresolve(),但没有成功。没有计时器,我也能做到。

这是我调用方法的地方:

$.when(cover.start()).done(function() {
    console.log("Cover has started.");
});

这是整个方法:

return {

    other: function() {},

    start: function() {
        var dfd = $.Deferred();
        el.filter.animate({
            "opacity": "0.6", "filter": "alpha(opacity=60)"
        }, 2000, "easeInOutCirc", function() {
            el.share.removeClass('fa-spin');

            setTimeout(function() {
                el.share.removeClass('fa-cog').addClass('fa-bars');
            },1000);

            setTimeout(function() {
                el.scroll.animate({
                    "opacity": "1",
                    "bottom": "40px"
                }, 1200, "easeOutBounce", function() {
                    var pulseOptions = { opacity: "0" };
                    setTimeout(function() {
                        el.scroll.pulse(pulseOptions, {
                            duration : 400,
                            pulses: 3,
                            interval: 500,
                            returnDelay: 800
                        });
                    }, 2000);
                    dfd.resolve();
                });
            }, 2000);

            return dfd.promise();

        });
    }

} // end return

如您所见,在我最初的尝试失败后,我将 dfd.resolve() 添加到我想要回调的位置并尝试 return 承诺。但是,该功能仍然过早触发。我哪里错了?

问题是,您需要从启动方法return promise

return {

    other: function () {},

    start: function () {
        var dfd = $.Deferred();
        el.filter.animate({
            "opacity": "0.6",
                "filter": "alpha(opacity=60)"
        }, 2000, "easeInOutCirc", function () {
            el.share.removeClass('fa-spin');

            setTimeout(function () {
                el.share.removeClass('fa-cog').addClass('fa-bars');
            }, 1000);

            setTimeout(function () {
                el.scroll.animate({
                    "opacity": "1",
                        "bottom": "40px"
                }, 1200, "easeOutBounce", function () {
                    var pulseOptions = {
                        opacity: "0"
                    };
                    setTimeout(function () {
                        el.scroll.pulse(pulseOptions, {
                            duration: 400,
                            pulses: 3,
                            interval: 500,
                            returnDelay: 800
                        });
                    }, 2000);
                    dfd.resolve();
                });
            }, 2000);


        });
        //need to return from start
        return dfd.promise();
    }

} // end return

不是为了窃取 APJ 的代表'而是出于兴趣,您可以通过利用 .delay().promise() 来避免回调地狱,这两者都与默认的 "fx" 动画队列有关.

以下几行内容可以解决问题,并且更具可读性:

//animation maps
var maps = [];
maps[0] = { 'opacity':0.6, 'filter':'alpha(opacity=60)' };
maps[1] = { 'opacity':1, 'bottom':'40px' };
maps[2] = { 'opacity':0 };
maps[3] = { 'duration':400, 'pulses':3, 'interval':500, 'returnDelay':800 };

//animation functions
var f = [];
f[0] = function () {
    return el.filter.animate(maps[0], 2000, "easeInOutCirc").promise();
};
f[1] = function () {
    return el.share.removeClass('fa-spin').delay(1000).promise();
};
f[2] = function () {
    return el.share.removeClass('fa-cog').addClass('fa-bars').delay(1000).promise();
};
f[3] = function () {
    el.scroll.animate(maps[1], 1200, "easeOutBounce").promise();
}
f[4] = function () {
    return el.scroll.delay(2000).promise();//delay() could be called on any element. `el.scroll` is arbitrary.
};
f[5] = function () {
    el.scroll.pulse(maps[2], maps[3]);
};

return {
    other: function () {},
    start: function () {
        //animation sequence
        var p = f[0]().then(f[1]).then(f[2]).then(f[3]);
        p.then(f[4]).then(f[5]);
        return p;//<<<< and here's the all important return
    }
}

不确定这是否 100% 正确 - 可能需要一些工作。

值得注意的是,这种方法在性能上有利有弊:

  • 优点:可重复使用的动画贴图;可重复使用的功能;
  • 缺点:更自由地使用 promises 会导致更大的内存峰值。