for*_*ice 0 javascript jquery jquery-deferred
我阅读了关于使用jQuery Deferred的这个问题的最佳答案.
我正在遍历一系列ID.对于每个ID,我需要从ajax请求获取与之相关的数据,或者如果ajax请求之前已成功返回数据,则需要从缓存中获取数据.
在每个循环中,我使用$ .when()来观察getData()是否在处理该ID之前从缓存或成功的ajax调用返回一些内容.目前的问题是ID处理无论如何都要继续进行,而不必等待getData()的ajax成功.
一些伪代码:
var IDs = ["1", "2", "1", "3", "1"];
//ID "1" is repeated
//data for "1" should should require ajax get the first time
//subsequent processing should get data for "1" from dataCache
var dataCache = [];
function getData(ID){
if (/*data for ID in dataCache*/){
//return data pertaining to ID from dataCache
} else {
return $.getJSON("returnJSONDataByID/" + ID, function(resp){
//push resp data to dataCache
})
}
}
for (/*each item i in IDs*/){
$.when(getData(IDs[i])).then(function(){
//process IDs[i] data
//this is the resolved handler, which should be executed
//when either getData() returns data from the dataCache,
//or $.getJSON succeeds
//PROBLEM: this is currently executing every loop and
//and doesn't wait for the ajax to return resp
})
}
Run Code Online (Sandbox Code Playgroud)
问题是你的循环会getData立即触发所有调用,但是只有在JSON调用返回后,结果才会存储在缓存中.因此,对于循环中的每个调用,缓存仍然为空,并且每个调用都将执行新的JSON请求.
解决方案:而不是结果存储Deferred缓存中的对象.
var IDs = ["1", "2", "1", "3", "1"];
var dataCache = {};
function getData(id) {
if (id in dataCache) {
console.log("Cache hit for ID " + id);
return dataCache[id];
} else {
console.log("Retrieving data for ID " + id);
var deferred = $.getJSON("http://jsfiddle.net/echo/jsonp/?callback=?", {
id: id
}, function(response) {
console.log("Retrieved data for ID " + id);
});
dataCache[id] = deferred;
return deferred;
}
}
for (var i=0; i<IDs.length; i++) {
$.when(getData(IDs[i])).then(function(result) {
console.log("result: " + result.id);
});
}
Run Code Online (Sandbox Code Playgroud)
注意:这是工作代码,你可以在jsFiddle中使用它.