J'ai une très longue page qui charge dynamiquement les images lorsque les utilisateurs défilent.
Toutefois, si un utilisateur quitte rapidement une certaine partie de la page, je ne souhaite pas que les images continuent à être chargées dans cette partie de la page qui est maintenant masquée.
Outre le chargement d'images, de nombreuses autres requêtes se produisent simultanément sur la page. Par conséquent, un déclenchement brus de window.stop () sur l'événement de défilement n'est pas acceptable.
J'ai essayé de supprimer et d'effacer les attributs img src pour les images qui ne sont plus visibles, mais, comme la demande avait déjà été lancée, le chargement de l'image se poursuit.
Rappelez-vous que l'image src a été remplie lorsque l'utilisateur a fait défiler brièvement cette partie de la page. Une fois passée, je ne pouvais pas obtenir cette image en arrêtant le chargement sans utiliser window.stop (). Clearing src n'a pas fonctionné. (Chrome et FF)
Des articles similaires que j'ai trouvés se rapprochent, mais ne semblent pas résoudre ce problème:
Ce que vous essayez de faire est la mauvaise approche, comme mentionné par nrabinowitz . Vous ne pouvez pas simplement "annuler" le processus de chargement d'une image (définir l'attribut src
sur une chaîne vide est ce n'est pas une bonne idée ). En fait, même si vous le pouviez, cela ne ferait qu'empirer les choses, car votre serveur enverrait continuellement des données qui seraient annulées, ce qui augmenterait son facteur de charge et le ralentirait. Aussi, considérez ceci:
Souvent, les problèmes informatiques sont simplement des problèmes de conception.
** MODIFIER **
Voici une idée:
votre page doit afficher les conteneurs DIV
avec la largeur et la hauteur de la taille d'image attendue (utilisez CSS pour styler). À l'intérieur de chaque DIV
, ajoutez un lien. Par exemple :
<div class="img-wrapper thumbnail">
<a href="http://www.domain.com/path/to/image">Loading...</a>
</div>
Ajouter ce code Javascript (non testé, l'idée est auto-descriptive)
$(function() {
var imgStack;
var loadTimeout;
$(window).scroll(function() {
imgStack = null;
if (loadTimeout) clearTimeout(loadTimeout);
loadTimeout = setTimeout(function() {
// get all links visible in the view port
// should be an array or jQuery object
imgStack = ...
loadNextImage();
}, 200); // 200 ms delay
});
function loadNextImage() {
if (imgStack && imgStack.length) {
var nextLink = $(imgStack.pop()); // get next image element
$('<img />').attr('src', nextLink.attr('href'))
.appendTo(nextLink.parent())
.load(function() {
loadNextImage();
});
// remove link from container (so we don't precess it twice)
nextLink.remove();
}
};
});
Eh bien, mon idée:
1) lancer une demande AJAX pour l'image; si l'opération aboutit, l'image est placée dans la mémoire cache du navigateur, et une fois que vous avez défini l'attribut 'src', l'image est affichée à partir du cache
2) vous pouvez abandonner le XHR
J'ai écrit un petit serveur avec express imitant l'énorme téléchargement d'images (il attend 20 secondes, puis renvoie une image). Ensuite, j'ai ceci dans mon HTML:
<!DOCTYPE html>
<html>
<head>
<style>
img {
width: 469px;
height: 428px;
background-color: #CCC;
border: 1px solid #999;
}
</style>
</head>
<body>
<img data-src="./img" src="" />
<br />
<a id="cancel" href="javascript:void(0)">CANCEL</a>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script>
$(function () {
var xhr, img = $('img'), src = img.data('src');
xhr = $.ajax(src, {
success: function (data) { img.attr('src', src) }
});
$('#cancel').click(function (){
xhr.abort();
})
});
</script>
</body>
</html>
Vous pouvez charger vos images à l’aide d’appels ajax et, au cas où l’utilisation se déroulerait, vous pouvez abandonner les appels.
Dans le pseudo-code jQuery, ce serait quelque chose comme ça (pardonnez-moi les erreurs de syntaxe, ce n'est qu'un exemple):
1) taguer les images que vous voulez charger
$(".image").each( function(){
if ( is_in_visible_area(this) ) { // check [1] for example
$(this).addClass("load_me");
} else {
$(this).addClass("dont_load");
}
});
2) charger des images
ajax_requests = {};
$(".image.load_me").each( function(){
// load image
var a = $.ajax({
url: 'give_me_photos.php',
data: {img: photo_id},
success: function(html){
photo_by_id(photo_id), img.append(html);
}
});
ajax_requests[photo_id] = a;
});
3) annuler le chargement de ceux-ci hors de l'écran
for( id in ajax_requests ) {
if ( ! is_in_visible_area(id) ) {
ajax_requests[id].abort();
}
}
Bien sûr, ajoutez aussi quelques vérifications si l’image est déjà chargée (par exemple la classe "chargée")
Utilisez une pile pour gérer les requêtes ajax (cela signifie que vous aurez un chargement en série au lieu de parallèle mais cela en vaut la peine)
À l’arrêt du défilement, attendez 300 ms, puis empilez toutes les images de la zone de vue
Chaque fois qu'un utilisateur fait défiler, vérifiez si une pile est en cours d'exécution. (fyi - vous pouvez arrêter toutes les requêtes sur une URL particulière au lieu de tuer tous les appels ajax. Vous pouvez aussi utiliser regex pour ne pas arrêter les autres requêtes sur la page.)
Si une pile existante est en cours d'exécution, affichez toutes les images qui s'y trouvent, à l'exception de la première.
Sur tous les appels ajax - lie l'événement beforeSend () pour supprimer cette image particulière de la pile
Il est tard aujourd'hui, mais nous avons fait quelque chose de très similaire au travail - si vous avez besoin du code détaillé, faites-le-moi savoir.
À votre santé!
Peut-être que vous pourriez servir l'image via un script php qui vérifierait un champ de la base de données (ou mieux encore un memcached) qui indiquerait l'arrêt du chargement. le script divise l'image en fragments, fait une pause entre chaque morceau et vérifie si l'indicateur d'arrêt de la demande est bien défini. Si cette option est définie, l'en-tête n'est pas envoyé avec A 204, il ne contiendra plus de contenu dès que le navigateur l'aura reçu.
Cela peut toutefois être un peu trop fatal.
BTW, une autre idée qui pourrait fonctionner:
1) créer un nouveau iframe
2) à l'intérieur de l'iframe, le script qui commence à charger l'image, puis une fois chargée, appelle la méthode .parent
3) en cas de besoin, arrêtez le chargement du contenu iframe à l’aide de .stop
sur l’objet iframe
La solution pourrait être un webworker. un webworker peut être résilié et avec lui la connexion . Mais il y a un petit problème: le webworker utilise les connexions limitées du navigateur et l'application est bloquée.
En ce moment, je travaille sur une solution avec serviceWorkers - ils n'ont pas de limite de connexion (je l'espère)