我有一个脚本,它使用jQuery的getScript()
函数从tumblr帐户动态加载博客帖子。
脚本响应是一个JSON结构tumblr_api_read
,其中包含(除其他外)图像网址。
function read(blogName) {
var imageUrls = [];
$.getScript("http://" + blogName + ".tumblr.com/api/read/js", function() {
imageUrls = getImageUrls(tumblr_api_read.posts); // returns an array of URLs to use as img src attributes
}).done(function(script, textStatus) {
loadImages(imageUrls);
processTumblrResponse(); // ### ONLY EXECUTE WHEN IMAGES ARE LOADED!!
});
}
我在函数loadImages()中使用imageUrls数组,通过jquery-built var <img/>
将$temporaryImageContainer
注入DOM,然后进行一些进一步的处理。
var imgAjaxComplete = false;
var imgCount = 0;
function loadImages(imageUrls, $temporaryImageContainer) {
while (!imgAjaxComplete) {
for (srcKey in imageUrls) {
var $image = $("<img>", {"id" : "imageUrl" + srcKey, "src" : imageUrls[srcKey]})
.load(function() {
if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {
console.log("Error loading image: " + imageUrls[srcKey]);
} else {
$temporaryImageContainer.append($image);
console.log("Loaded image: " + imageUrls[srcKey]);
}
});
++imgCount;
}
if (imgCount == imageUrls.length) {
imgAjaxComplete = true;
imgCount = 0;
}
}
console.log("loadImages() complete");
}
function processTumblrResponse() {
console.log("Images loaded. Running processTumblrResponse()");
// further processing here...
}
问题在于,for
中的loadImages()
循环在其他任何事情之前执行(我认为这无论发生了什么)并且它只会尝试加载最后一张图片src在imageUrls
n次(其中n是imageUrls.length
)。
在执行额外处理之前,是否可以确定注入DOM的所有图像何时完成加载?
JSON太大了,无法发布到此处,但请告诉我上下文是否需要。
答案 0 :(得分:2)
用此处替换您的函数loadImages
:
function loadImages(imageUrls, $temporaryImageContainer) {
for (srcKey in imageUrls) {
var $image = $("<img>", {"id" : "imageUrl" + srcKey, "src" : imageUrls[srcKey]})
.load(function() {
if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {
console.log("Error loading image: " + imageUrls[srcKey]);
} else {
$temporaryImageContainer.append($image);
console.log("Loaded image: " + imageUrls[srcKey]);
}
imgCount++;
checkIfImagesAreLoaded();
});
}
}
function checkIfImagesAreLoaded() {
if (imgCount === imageUrls.length) {
imgCount = 0;
imgAjaxComplete = true;
console.log("loadImages() complete");
}
}
至于解释,for循环在其他任何事情之前完成,因为jQuery load
函数只在加载图像时执行作为参数传入的方法,因此不会立即调用它。
修改强>
您不应该在Javascript中使用for (x in array)
,因为此循环用于迭代对象的属性。不幸的是,最佳做法是使用for (var i = 0; i < length; i++) ...
。
请参阅W3Schools获取循环文档here。
你也可以使用:
yourArray.forEach(function(item) {
//Do crazy stuff here
});
但是forEach()
是ES5的一部分,在IE8及以下版本的旧浏览器中不支持它。