我在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”按钮上单击两次,显示两个警报。
是否有任何方法可以解决问题,因此当解析延迟对象时,它只调用一次,因为方法名称相同。
抱歉可能是我没有正确解释问题,代码只是为了证明问题。因为方法名称相同所以不应该调用它两次,或者问问题的方法是 - 是否有任何方法来检查延迟对象的队列,所以我可以看到有多少方法附加到延迟对象,如果方法已经附加,所以不要再次附加它。 很抱歉不清楚。
答案 0 :(得分:2)
首先点击changeDeferred
功能集resolveDeferred
至true
,然后将myDoneMethod
添加至objDeferred
。
在第二次点击后,您再次将myDoneMethod
添加到objDeferred
并解决它。
解析后调用所有done
,你添加两个回调 - 两个回调。
答案 1 :(得分:2)
这可以满足您的需求,使用您自己的队列来检查任何重复的回调:
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()
简单。.done()
队列中。.doneUnique()
模仿.done()
,因为它会处理多个参数(一次调用中有多个回调)。.doneUnique()
表现得像.done()
。