要实现的功能
- 连续加载多张图片
- 加载错误, 超时后显示加载失败图片
为了实现上述功能, 需要处理图片加载状态事件以及完成时的回调函数, 针对这种状态通知的特点, 适合采用 Promise 进行处理。
实现步骤
完成一个加载图片的代理创建函数, 该函数具有处理图片加载失败、 成功、 超时监控、 取消加载超时监控的能力
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59function createLoadImgProxy() {
var imgCache = new Image();
var promise = new Promise(function(resolve, reject) {
//加载完成事件处理,加载完成后进行resolve操作
imgCache.onload = function() {
resolve(this.src);
};
//加载终止事件处理,终止后进行reject操作
imgCache.onabort = function() {
reject("aborted");
};
//加载异常事件处理,异常后进行reject操作
imgCache.onerror = function() {
reject("error");
};
});
var timeoutTimer;
//开始加载超时监控,超时后进行reject操作
function beginTimeoutWatcher() {
timeoutTimer = setTimeout(function() {
promise.reject('timeout');
}, 10000);
}
//结束加载超时监控
function endTimeoutWatcher() {
if (!timeoutTimer) {
return;
}
clearTimeout(timeoutTimer);
}
return function(eleImg, src) {
// 加载本地图片
loadImg(eleImg, '../images/loading.gif');
imgCache.src = src;
//开始进行超时加载监控
beginTimeoutWatcher();
return promise.then(function(src) {
// alert('done end');
//加载完成后,往图片元素上设置图片
loadImg(eleImg, src);
}).catch(function(msg) {
// alert('fail end:' + msg);
//加载失败后,往图片元素上设置失败图片
loadImg(eleImg, '../images/loadFailed.jpg');
}).finally(function() {
// alert('always end');
//加载完成或加载失败都要终止加载超时监控
endTimeoutWatcher();
});
};
}连续加载多张图片
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21//一张一张的连续加载图片
//参数:srcs: 图片路径数组
function doLoadImgs(srcs) {
var index = 0;
(function loadOneByOne() {
//退出条件
if (!(src = srcs[index++])) {
return;
}
var eleImg = createImgElement();
document.getElementById('imgContainer').appendChild(eleImg);
//创建一个加载代理函数
var loadImgProxy = createLoadImgProxy();
//在当前图片加载或失败后,递归调用,加载下一张
loadImgProxy(eleImg, src).then(loadOneByOne);
})();
}
做一个 loadOneByOne 的加载递归函数,内部先创建一个加载代理,在代理加载完图片,不管是成功还是失败后,递归调用 loadOneByOne 函数加载下一张图片。
关键就在于代理函数返回的 promise 对象,使用 .then 方法可在加载完成后(成功或失败)进行 loadOneByOne 递归调用加载下一张。
完整代码如下:
1 |
|