如何为重载的jQuery函数添加promise?

时间:2014-10-02 16:57:05

标签: jquery promise overloading

我正在使用this other question中的代码覆盖jQuery的fadeOut以使用css转换。

代码

(function ($) {
    $.fn.fadeIn = function (speed, easing, callback) {
        return this.filter(function (i, elem) {
                        return $.css(elem, 'display') === 'none' || !$.contains(elem.ownerDocument, elem);
                    })
                    .css('opacity', 0)
                    .show()
                    .end()
                .transition({
                    opacity: 1
                }, speed, easing, callback);
    };

    $.fn.fadeOut = function (speed, easing, callback) {
        var newCallback = function () {
            $(this).hide();
        };

        // Account for `.fadeOut(callback)`.
        if (typeof speed === 'function') {
            callback = speed;
            speed = undefined;
        }

        // Account for `.fadeOut(options)`.
        if (typeof speed === 'object' && typeof speed.complete === 'function') {
            callback = speed.complete;
            delete speed.complete;
        }

        // Account for `.fadeOut(duration, callback)`.
        if (typeof easing === 'function') {
          callback = easing;
          easing = undefined;
        }

        if (typeof callback === 'function') {
            newCallback = function () {
                $(this).hide();
                callback.apply(this, arguments);
            };
        }

        return this.transition({
            opacity: 0
        }, speed, easing, newCallback);
    };
}(jQuery));

这适用于

“正常通话”

$('body')
    .find('.item')
        .fadeOut()
    .end()
    // ...

但不是

“承诺电话”

$('body')
    .find('.item')
        .fadeOut(function(){ $(this).remove() })
        .promise()
        .done(function allDone(){ /*...*/ })
    .end()
    // ...
我希望使用

以便allDone()在所有项目淡出后仅运行一次。所以我修改了代码(基于我可以通过谷歌搜索得到的)到

(function ($) {
    $.fn.fadeOut = function (speed, easing, callback) {
        var dfd = new $.Deferred();    //################# Added

        var newCallback = function () {
            $(this).hide();

            dfd.resolve(this);    //################# Added
        };

        // Account for `.fadeOut(callback)`.
        if (typeof speed === 'function') {
            callback = speed;
            speed = undefined;
        }

        // Account for `.fadeOut(options)`.
        if (typeof speed === 'object' && typeof speed.complete === 'function') {
            callback = speed.complete;
            delete speed.complete;
        }

        // Account for `.fadeOut(duration, callback)`.
        if (typeof easing === 'function') {
          callback = easing;
          easing = undefined;
        }

        if (typeof callback === 'function') {
            newCallback = function () {
                $(this).hide();
                callback.apply(this, arguments);
                dfd.resolve(this);    //################# Added
            };
        }

        this.transition({    //################# return was moved below
            opacity: 0
        }, speed, easing, newCallback);

        return dfd.promise();
    };
}(jQuery));

似乎使“承诺呼叫”工作,但现在我在“正常呼叫”的控制台中得到undefined is not a function。我是以错误的方式解决这个问题吗?

我怎样才能满足这两个电话?

1 个答案:

答案 0 :(得分:1)

假设您使用的.fadeOut方法正确设置了动画队列,那么您的自定义.transition函数无法与.promise一起使用。如果.promise无法正常工作,请提交针对该问题的错误" transit"你正在使用的插件,不要试图自己想出一些东西。

你得到undefined is not a function异常的原因是.promise()确实返回了一个Promise对象,它有各种chainable methods但不是jQuery集合,并且没有.end()方法!你正在打破链条,你需要使用

var body = $('body');
body.find('.item')
    .fadeOut(function(){ $(this).remove() })
    .promise()
    .done(function allDone(){ /*...*/ });
body.… // the rest