我有一个绑定到$someEl
的事件处理程序,它只应在oRes
填充数据时执行,数据可以来自主要来源(getData1()
)或备份来源( getData2()
)。仅当主要源超时时才从备份源请求数据。
如果主要来源没有超时,那么一切正常;但是,当调用备份getData2()
函数时,dfd
永远不会被解析,因此当我点击$someEl
时没有任何记录。我怀疑它无法正常工作,因为getData2()
中的Deferred对象正在覆盖dfd
点击处理程序所指的$someEl
变量。
我有一种感觉,我没有使用"最佳实践"来应用延期/承诺。图案。鉴于这种情况,如何使点击处理程序正确等待oRes在超时后从主AJAX响应或辅助AJAX响应中填充?
一些澄清说明:
getData1()
必须在文档准备好后执行$someEl.click()
可能会在文档加载过程中随时触发,因此需要在$(document).ready()
以下是代码:
var oRes, dfd;
// Get data from primary source
function getData1() {
dfd = $.ajax({
...
success: function(data) {
oRes = data;
},
error: function(jqXHR, textStatus, errorThrown) {
if (textStatus==='timeout') getData2();
},
timeout: 10000 // 10-second timeout
});
}
// Get data from backup source
function getData2() {
dfd = $.ajax({...});
}
$someEl.click(function() {
dfd.done(function() {
console.log('This should only log when oRes is ready');
});
});
$(document).ready(function() {
getData1();
});
我在这支笔中模拟了我的情况:http://codepen.io/thdoan/pen/pyVyKj
基本上,我无法让事件处理程序输出"数据准备就绪!"填充oRes
时,无需在加载页面后手动点击该框。
答案 0 :(得分:0)
我会在ajax请求的回调中包含函数调用。
var oRes = null;
var dfd = null;
// Get data from backup source
function getData2() {
dfd = $.ajax({...});
}
// Get the primary data source
function getData1() {
dfd = $.ajax({
success: function(data) {
oRes = data;
// set the click handler when oRes is successfully set
$(someEl).click(function() {
console.log('This should only log when oRes is ready');
});
},
error: function(jqXHR, textStatus, errorThrown) {
if (textStatus==='timeout') getData2();
},
always: function(){
if (oRes==null){
getData2();
}
}
timeout: 10000 // 10-second timeout
});
}
答案 1 :(得分:0)
我认为你只需要提升一个级别。
创建一个您的点击处理程序将侦听的延迟前台(并且该实例不会更改)。
然后,您可以解决从getData1()
或getData2()
var oRes,
// Resolve this deferred when data has been successfully loaded:
dfd = $.Deferred(),
// But add listeners to this promise:
dfdPromise = dfd.promise();
// Get data from primary source
function getData1() {
$.ajax({
...
success: function(data) {
oRes = data;
// Resolve when data loaded:
dfd.resolve(data);
},
error: function(jqXHR, textStatus, errorThrown) {
if (textStatus==='timeout') getData2();
},
timeout: 10000 // 10-second timeout
});
}
// Get data from backup source
function getData2() {
$.ajax({...})
.then(function(data){
// Fallback data resolve:
dfd.resolve(data);
});
}
$someEl.click(function() {
dfdPromise.done(function() {
console.log('This should only log when oRes is ready');
});
});
$(document).ready(function() {
getData1();
});