我正在使用长轮询来检索带有图片网址的大型json Feed。我是在success
请求的$.ajax
部分中预加载这些网址,并希望在完全加载后调用函数对这些图像执行某些操作。我尝试使用$.Deferred
请求的complete
部分中的$.ajax
对象,并在图像预加载循环结束时解析$.Deferred
来实现此目的。< / p>
但是,当我监视控制台时,我可以看到在图像预加载时继续进行$.ajax
调用。 $.Deferred
直到预加载循环结束才解决,所以我不明白为什么会发生这种情况。我对$.Deferred
的了解有限,但我正在努力学习更多,所以对于为什么会发生这种情况有任何建议,如何解决这个问题会很棒。我得到的理解是,它们是一种阻止函数被保留的方法,直到它们被保留...
作为奖励,除了丑陋的代码之外,还有一个问题是发出多个$.ajax
请求并对返回的数据做同样的事情?感谢
$(function(){
(function poll(){
var streamUrl = 'http://demofeed';
var def = $.Deferred();
console.log('about to get');
setTimeout(function(){
$.ajax({
url: streamUrl,
dataType: 'json',
success: function(data) {
createArray(data, def);
},
complete: function () {
$.when(def).done(function() {
//Long-poll again
poll();
});
},
error: function(){
setTimeout(function(){
console.log('There was an error with the XHR Request');
poll();
}, 3000);
}
});
}, 7000);
})();
});
function createArray(data, defer){
console.log('creating array');
var entries = data['entries'];
for (var k = 0, j = entries.length; k < j; k++) {
console.log('there is new media');
if (entries[k].img) {
var img = new Image();
img.onload = (function(entry) {
return function() {
validArray.push(entry);
console.log('New Media Loaded');
}
})(entries[k]);
img.onerror = function(){
console.log('error: bad image source');
};
img.src = entries[k].url;
} else {
console.log('Not an image');
}
}
defer.resolve(); //Here is where I resolve the deferred object, once for loop is done (all images have been loaded)
}
答案 0 :(得分:3)
$.when
等待 promises 。
您正在传递一个延迟对象。它反过来通过包装它转换为一个承诺,所以等待它立即产生它作为值。所以.when
立即执行。您可以使用def.promise()
来获得承诺。
那就是说,如果我是你,我可能会做一个更有说服力的API。
var delay = function(ms){
var def = $.Deferred();
setTimeout(function(){ def.resolve(); },ms);
return def.promise();
}
让我这样做:
function poll(){
console.log('about to get');
return delay(7000).then(function(){
return $.get('http://demofeed');
}).then(function(){ // success case
return createArray(data); // we'll get to it later
}), function(){ // handle error
console.log('There was an error with the XHR Request');
return delay(3000); // wait 3 ms
}).then(poll); // long poll
}
看看它是多么清晰和热它只有两个级别的缩进,这是因为promises链。如果您的代码是连续的,那么大致如下:
function poll(){
sleep(7000);
try{
var data = $.get('http://demofeed'); // assume this is sync
arr = createArray(data);
} catch(e) {
console.log("There was an error with the XHR Request");
sleep(3000);
}
poll(); /// call again
}
对于加载图像功能,请考虑使用$.when.apply
让$.when
等待多个值:
function createImages(data){ // what does this return?
var promises = data.entries.map(function(entry){
var img = new Image();
var d = $.Deferred();
img.onload = function(entry){ d.resolve(entry); };
img.onerror = function(){ console.log("Bad Image usage"); }
return d.promise();
});
// this will actually _wait_ for the images now.
return $.when.apply($, promises);
}
最后请注意,如果我是你,我会避免使用jQuery承诺并使用像Bluebird这样更强大的库。