Jquery promise implements image loading one by one
- 2020-10-23 20:53:39
- OfStack
Promise is specification 1 of CommonJS, with resolve, reject, done, fail, then and other methods, which can help us control the flow of code and avoid multi-layer nesting of functions. Asynchronism is becoming more and more important in web development. For developers, this kind of non-linear programming can be difficult to control, while Promise gives us more control over the execution process of the code. Popular js libraries such as jQuery already implement this object, and ES6, which will be released later this year, will implement Promise native.
In the javascript design pattern practice of the proxy mode - image preloading using the proxy mode to realize the image preloading function.
Now take it one step further and complete a feature that allows you to load successive images one by one.
Function:
1.1 One loading picture.
2. Loading error. After timeout, images of failed loading are displayed.
For functional requirements, there is bound to be handling of loadstate events and final-time callbacks, which not only creates code clutter, but also breaks principles that are no longer written in the usual way. In view of the characteristics of this status notification, it is more appropriate to adopt promise architecture for processing. promise is essentially one of the subscription publish design patterns. Currently, this function is developed with promise which comes with jquery.
1. Complete 1 agent creation function to load the image, which can generate 1 agent with load timeout, failure, success and cancellation monitoring capability.
function createLoadImgProxy(){
var imgCache = new Image();
var dfd = $.Deferred();
var timeoutTimer;
// Start loading timeout monitoring and proceed after timeout reject operation
function beginTimeoutWatcher(){
timeoutTimer = setTimeout(function(){
dfd.reject('timeout');
}, 10000);
}
// End load timeout monitoring
function endTimeoutWatcher(){
if(!timeoutTimer){
return;
}
clearTimeout(timeoutTimer);
}
// Load completion event processing, after the load is completed resolve operation
imgCache.onload = function(){
dfd.resolve(this.src);
};
// Load termination event processing, after termination reject operation
imgCache.onabort = function(){
dfd.reject("aborted");
};
// Load exception event handling, after the exception reject operation
imgCache.onerror = function(){
dfd.reject("error");
};
return function(eleImg, src){
dfd.always(function(){
// The load timeout monitoring is terminated when the load completes or fails
endTimeoutWatcher();
}).done(function(src){
// When the load is complete, set the image on the image element
loadImg(eleImg, src);
}).fail(function(msg){
// After failing to load, set the failed image to the image element
loadImg(eleImg, 'loadFailed.jpg');
});
loadImg(eleImg, 'loading.gif');
imgCache.src = src;
// Timeout loading monitoring begins
beginTimeoutWatcher();
return dfd.promise();
};
}
An Deferred object is created as follows
var dfd = $.Deferred();
The Deferred object fires the completion event through the resolve method, and the done method responds to the completion event.
The completion event when the load succeeds.
imgCache.onload = function(){
dfd.resolve(this.src);
};
And the response processing when the load is complete, which is to set the image to the element, the following code is the above chain of the demolition.
dfd.done(function(src){
// When the load is complete, set the image on the image element
loadImg(eleImg, src);
});
The Defferred object fires the rejection event via the reject method and USES the fail method to respond to the rejection event, indicating that the load failed.
Reject event during load timeout, termination, exception.
// Start loading timeout monitoring and proceed after timeout reject operation
function beginTimeoutWatcher(){
timeoutTimer = setTimeout(function(){
dfd.reject('timeout');
}, 10000);
}
// Load termination event processing, after termination reject operation
imgCache.onabort = function(){
dfd.reject("aborted");
};
// Load exception event handling, after the exception reject operation
imgCache.onerror = function(){
dfd.reject("error");
};
And the response processing when the load failed to set the failed image.
dfd.fail(function(msg){
// After failing to load, set the failed image to the image element
loadImg(eleImg, 'loadFailed.jpg');
});
At the end of the proxy function, the promise object of deferred is returned to monitor the completion and failure states of the load at the point of call, so that the next image is loaded.
return dfd.promise();
2.1 Continuous one-sheet loading
//1 zhang 1 A continuous load of pictures
// Parameters:
// srcs: Image path array
function doLoadImgs(srcs){
var index = 0;
(function loadOneByOne(){
// Exit criteria
if(!(s = srcs[index++])) {
return;
}
var eleImg = createImgElement();
document.getElementById('imgContainer').appendChild(eleImg);
// create 1 A load proxy function
var loadImgProxy = createLoadImgProxy();
// After the current picture loads or fails, recursively call under load 1 zhang
loadImgProxy(eleImg, s).always(loadOneByOne);
})();
}
Do a load recursive function for loadOneByOne.
Internally, 1 loading agent is created. After the agent loads the image, no matter it succeeds or fails, it recursively calls the loadOneByOne function to load the next image.
The key lies in the promise object returned by the proxy function. The.always method can be used to make a recursive call to loadOneByOne to load the next slide after it has been loaded (successfully or not).
loadImgProxy(eleImg, s).always(loadOneByOne);
That's it.
With the adoption of the promise mode, the callback function is gone, as are the functions that maintain state and internal variables, and the code is clearer and simpler, so that the 1 consistency between the proxy function and the local function is protected.
Complete code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<button id='btnLoadImg'> Loading pictures </button>
<br>
<div id='imgContainer'>
</div>
<br>
<script type='text/javascript' src="./jquery-1.11.3.min.js"></script>
<script type='text/javascript'>
var imgSrcs = [
'http://img.wanchezhijia.com/A/2015/3/20/17/11/de63f77c-f74f-413a-951b-5390101a7d74.jpg',
'http://www.newbridgemotorsport.com/files/6413/9945/0406/IMG_3630.jpg',
'http://www.carsceneuk.com/wp-content/uploads/2015/03/88y9989.jpg',
'http://mfiles.sohu.com/20130223/5ff_403b2e7a_7a1f_7f24_66eb_79e3f27d58cf_1.jpg',
'http://img1.imgtn.bdimg.com/it/u=2678963350,1378052193&fm=21&gp=0.jpg'
];
$(document).ready(function(){
$('#btnLoadImg').bind('click', function(){
doLoadImgs(imgSrcs);
});
});
// create img The label
// I'm going to use the self-executing function plus 1 A closure, so that multiple can be created id different img The label.
var createImgElement = (function(){
var index = 0;
return function() {
var eleImg = document.createElement('img');
eleImg.setAttribute('width', '200');
eleImg.setAttribute('heght', '150');
eleImg.setAttribute('id', 'img' + index++);
return eleImg;
};
})();
function loadImg(img, src) {
img.src = src;
}
function createLoadImgProxy(){
var imgCache = new Image();
var dfd = $.Deferred();
var timeoutTimer;
// Start loading timeout monitoring and proceed after timeout reject operation
function beginTimeoutWatcher(){
timeoutTimer = setTimeout(function(){
dfd.reject('timeout');
}, 10000);
}
// End load timeout monitoring
function endTimeoutWatcher(){
if(!timeoutTimer){
return;
}
clearTimeout(timeoutTimer);
}
// Load completion event processing, after the load is completed resolve operation
imgCache.onload = function(){
dfd.resolve(this.src);
};
// Load termination event processing, after termination reject operation
imgCache.onabort = function(){
dfd.reject("aborted");
};
// Load exception event handling, after the exception reject operation
imgCache.onerror = function(){
dfd.reject("error");
};
return function(eleImg, src){
dfd.always(function(){
// alert('always end');
// The load timeout monitoring is terminated when the load completes or fails
endTimeoutWatcher();
}).done(function(src){
// alert('done end');
// When the load is complete, set the image on the image element
loadImg(eleImg, src);
}).fail(function(msg){
// alert('fail end:' + msg);
// After failing to load, set the failed image to the image element
loadImg(eleImg, 'loadFailed.jpg');
});
loadImg(eleImg, 'loading.gif');
imgCache.src = src;
// Timeout loading monitoring begins
beginTimeoutWatcher();
return dfd.promise();
};
}
//1 zhang 1 A continuous load of pictures
// Parameters:
// srcs: Image path array
function doLoadImgs(srcs){
var index = 0;
(function loadOneByOne(){
// Exit criteria
if(!(s = srcs[index++])) {
return;
}
var eleImg = createImgElement();
document.getElementById('imgContainer').appendChild(eleImg);
// create 1 A load proxy function
var loadImgProxy = createLoadImgProxy();
// After the current picture loads or fails, recursively call under load 1 zhang
loadImgProxy(eleImg, s).always(loadOneByOne);
})();
}
</script>
</body>
</html>