我正在学习如何使用jQuery的deferred,我注意到使用$.when
和.notifyWith
时遇到了问题。
我在不使用$.when
的情况下做了一个示例,.notifyWith
完美地运作
function a() {
var d = new $.Deferred,
$A = $('#A'),
$P = $('#P').progressbar();
setTimeout(function() {
$A.css('background-color', 'blue');
d.notifyWith($P, [.5]);
}, 2000);
setTimeout(function() {
$A.text('test');
d.notifyWith($P, [1]);
d.resolveWith($P, ['done']);
}, 4000);
return d.promise();
}
$('#G').click(function() {
a().progress(function(x) {
this.progressbar({
value: x * 100
});
}).done(function(x) {
alert(x)
});
});
DEMO:http://jsfiddle.net/NTICompass/3DDSa/3/
在.progress
内,this
设置为$P
,因此进度条移动正确。
我想将2 setTimeout
个动作分成不同的函数,所以我这样做并使用$.when
将promises合并为一个:
(function() {
var $P = $('#P').progressbar();
window.a = function() {
var d = new $.Deferred,
$A = $('#A');
setTimeout(function() {
$A.css('background-color', 'blue');
d.notifyWith($P, [.5]);
d.resolve('a()');
}, 2000);
return d.promise();
}
window.b = function() {
var d = new $.Deferred,
$A = $('#A');
setTimeout(function() {
$A.text('test');
d.notifyWith($P, [.5]);
d.resolve('b()');
}, 4000);
return d.promise();
}
}())
$('#G').click(function() {
$.when(a(), b()).progress(function(x, y) {
this.progressbar({
value: ((x || 0) + (y || 0)) * 100
});
}).done(function(x, y) {
alert(x + ' ' + y)
});
});
DEMO:http://jsfiddle.net/NTICompass/3DDSa/16/
由于某些原因,this
内的.progress
不 $P
。相反,它是延迟对象(或承诺对象,我不是很确定)。为什么this
不等于$P
?
答案 0 :(得分:2)
我不确定是否有理由按原样编写,但只需将第1336行promise
更改为this
即可使代码按预期运行。
$.when = function(firstParam) {
var args = [].slice.call(arguments, 0),
i = 0,
length = args.length,
pValues = new Array(length),
count = length,
pCount = length,
deferred = length <= 1 && firstParam && jQuery.isFunction(firstParam.promise) ? firstParam : jQuery.Deferred(),
promise = deferred.promise();
function resolveFunc(i) {
return function(value) {
args[i] = arguments.length > 1 ? [].slice.call(arguments, 0) : value;
if (!(--count)) {
deferred.resolveWith(deferred, args);
}
};
}
function progressFunc(i) {
return function(value) {
pValues[i] = arguments.length > 1 ? [].slice.call(arguments, 0) : value;
deferred.notifyWith(this, pValues); // this is line 1336
};
}
if (length > 1) {
for (; i < length; i++) {
if (args[i] && args[i].promise && jQuery.isFunction(args[i].promise)) {
args[i].promise().then(resolveFunc(i), deferred.reject, progressFunc(i));
} else {
--count;
}
}
if (!count) {
deferred.resolveWith(deferred, args);
}
} else if (deferred !== firstParam) {
deferred.resolveWith(deferred, length ? [firstParam] : []);
}
return promise;
};
可能值得添加到门票中。
答案 1 :(得分:2)
这在jQuery 1.8.0中得到修复,其中this
实际上是一个上下文数组。
$('#G').click(function() {
var index = 0;
$.when(a(), b()).progress(function(x, y) {
this[index++].progressbar({
value: ((x || 0) + (y || 0)) * 100
});
}).done(function(x, y) {
alert(x + ' ' + y)
});
});
DEMO:http://jsfiddle.net/3D4wq/1/(感谢来自jQuery bug跟踪器的jaubourg)
注意:.progress
(和.done
),arguments.length
内的内容始终是传递给$.when
的元素数量,因此this[arguments.length-1]
不会(总是)工作。
第一次.progress
被称为arguments
[.5, undefined]
。