jQuery延迟对象调用两次

时间:2013-12-06 11:07:27

标签: jquery jquery-deferred

我在jQuery 1.7中使用Deferred对象遇到了以下问题。这是我的问题的简化版本。跟随小提琴 -

http://jsfiddle.net/daljit/3gbrD/1/embedded/result/

以下是代码段。

var resolveDeferred = false;
var objDeferred = $.Deferred();

function changeDeferred() {
    objDeferred.done(myDoneMethod);
    if (resolveDeferred) {
        objDeferred.resolve();
    }
    resolveDeferred = true;
}

function myDoneMethod() {
    console.log("I am called");
}
<input type="button" value="clickMe" onclick ="changeDeferred()" />

我们可以看到在“clickme”按钮上单击两次,显示两个警报。

是否有任何方法可以解决问题,因此当解析延迟对象时,它只调用一次,因为方法名称相同。

抱歉可能是我没有正确解释问题,代码只是为了证明问题。因为方法名称相同所以不应该调用它两次,或者问问题的方法是 - 是否有任何方法来检查延迟对象的队列,所以我可以看到有多少方法附加到延迟对象,如果方法已经附加,所以不要再次附加它。 很抱歉不清楚。

3 个答案:

答案 0 :(得分:2)

首先点击changeDeferred功能集resolveDeferredtrue,然后将myDoneMethod添加至objDeferred。 在第二次点击后,您再次将myDoneMethod添加到objDeferred并解决它。 解析后调用所有done,你添加两个回调 - 两个回调。

答案 1 :(得分:2)

这可以满足您的需求,使用您自己的队列来检查任何重复的回调:

DEMO

var objDeferred = $.extend({}, $.Deferred(), {
    queue: [],
    done: function () {
        var callback = arguments[0];
        if (!~$.inArray(callback.toString(), this.queue)) {  
            this.queue.push(callback.toString());
            this.then($.proxy(function(){this.queue = [];callback()},this));
        }         
        return this
    }
});

答案 2 :(得分:1)

这是基于A Wolff答案的版本,但使用新方法.doneUnique(),让.done()可用于非唯一用途。

function myDeferred() {
    return $.extend({}, $.Deferred(), {
        dummyQueue: $.Callbacks(),
        doneUnique: function () {
            var that = this;
            $.each(arguments, function(i, fn) {
                if($.isArray(fn)) {
                    that.done(fn);//add arrays of callbacks unconditionally 
                }
                else if (!that.dummyQueue.has(fn)) {//test - already added?
                    that.done(fn);
                    that.dummyQueue.add(fn);//remember fn, so it's not added again
                }
            });
            return this;//for method chaining
        }
    });
}

<强> DEMO

注意:

  • 虚拟$.Callbacks()队列用于记住唯一回调而不是普通数组,允许使用.has(),这可以说比$.inArray()简单。
  • 成功通过唯一性陷阱的Callbak最终会出现在标准.done()队列中。
  • .doneUnique()模仿.done(),因为它会处理多个参数(一次调用中有多个回调)。
  • 提供传递回调数组。无条件地添加这样的数组(即,不对数组包装的回调进行唯一性检查)。这提供了强制.doneUnique()表现得像.done()
  • 的选项