如何在超时后使用 jQuery Deferred/Promise 和第二个 $.ajax()
How to use jQuery Deferred/Promise with a second $.ajax() after a timeout
我有一个绑定到 $someEl
的事件处理程序,它应该只在 oRes
填充数据时执行,数据可以来自主要来源 (getData1()
) 或备份来源(getData2()
)。仅当主源超时时才从备份源请求数据。
如果主源没有超时,那么一切正常;然而,当备份 getData2()
函数被调用时,dfd
永远不会被解析,所以当我点击 $someEl
时没有任何记录。我怀疑它不起作用,因为 getData2()
中的 Deferred 对象正在覆盖 $someEl
单击处理程序所引用的 dfd
变量。
我感觉我没有使用 "best practice" 模式来应用 Deferred/Promise。在这种情况下,您如何让点击处理程序正确等待 oRes 在超时后从主要 AJAX 响应或次要 AJAX 响应填充?
一些说明说明:
getData1()
必须在文档准备好后执行
$someEl.click()
可能会在文档加载期间随时触发,因此需要在 $(document).ready()
之外定义事件处理程序
- 我受困于 jQuery 1.7.1
代码如下:
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
被填充时,我无法让事件处理程序输出 "Data is ready!",而无需在页面加载后手动单击该框。
我会将函数调用包含在 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
});
}
我认为你只需要提高一个级别。
预先创建一个您的点击处理程序将监听的 Deferred(并且该实例不会更改)。
然后您解决从 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();
});
我有一个绑定到 $someEl
的事件处理程序,它应该只在 oRes
填充数据时执行,数据可以来自主要来源 (getData1()
) 或备份来源(getData2()
)。仅当主源超时时才从备份源请求数据。
如果主源没有超时,那么一切正常;然而,当备份 getData2()
函数被调用时,dfd
永远不会被解析,所以当我点击 $someEl
时没有任何记录。我怀疑它不起作用,因为 getData2()
中的 Deferred 对象正在覆盖 $someEl
单击处理程序所引用的 dfd
变量。
我感觉我没有使用 "best practice" 模式来应用 Deferred/Promise。在这种情况下,您如何让点击处理程序正确等待 oRes 在超时后从主要 AJAX 响应或次要 AJAX 响应填充?
一些说明说明:
getData1()
必须在文档准备好后执行$someEl.click()
可能会在文档加载期间随时触发,因此需要在$(document).ready()
之外定义事件处理程序
- 我受困于 jQuery 1.7.1
代码如下:
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
被填充时,我无法让事件处理程序输出 "Data is ready!",而无需在页面加载后手动单击该框。
我会将函数调用包含在 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
});
}
我认为你只需要提高一个级别。
预先创建一个您的点击处理程序将监听的 Deferred(并且该实例不会更改)。
然后您解决从 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();
});