it-swarm.com.de

Wie bricht ich Image-Ladevorgänge ab, ohne window.stop () zu verwenden?

Ich habe eine sehr lange Seite, auf der Bilder dynamisch geladen werden, während Benutzer blättern.

Wenn ein Benutzer jedoch schnell von einem bestimmten Teil der Seite wegblättert, möchte ich nicht, dass die Bilder in diesem jetzt nicht sichtbaren Teil der Seite weiter geladen werden.

Neben dem Laden von Bildern werden auf der Seite viele andere Anforderungen gleichzeitig ausgeführt. Daher ist ein stumpfes window.stop () - Auslösen des Scroll-Ereignisses nicht akzeptabel.

Ich habe versucht, die Attribute img src für Bilder zu entfernen und zu löschen, die nicht mehr angezeigt werden. Da die Anforderung jedoch bereits gestartet wurde, wird das Bild weiterhin geladen.

Denken Sie daran, dass das Bild src ausgefüllt wurde, während der Benutzer kurz an diesem Teil der Seite vorbeirollte. Einmal vorbei, konnte ich das Bild nicht mehr mit stop.load ohne window.stop () laden. Clearing src hat nicht funktioniert. (Chrome & FF)

Ähnliche Beiträge, die ich gefunden habe, kommen näher, scheinen aber dieses Problem nicht zu lösen:

43
Evan

Was Sie versuchen, ist der falsche Ansatz, wie von nrabinowitz erwähnt. Sie können den Ladevorgang eines Bildes nicht einfach "abbrechen" (das Attribut src auf einen leeren String zu setzen ist keine gute Idee ). Selbst wenn Sie dies tun könnten, würde dies die Dinge nur noch schlimmer machen, da Ihr Server ständig Daten sendet, die abgebrochen würden, wodurch der Auslastungsfaktor erhöht und verlangsamt würde. Bedenken Sie auch Folgendes:

  1. wenn Ihr Benutzer die Seite frenetisch auf und ab blättert, erwartet er einige Ladezeiten.
  2. eine Timeout-Verzögerung (z. B. 200 ms) vor dem Laden eines Teils der Seite ist ziemlich akzeptabel. Wie oft stoppt und springt einer nach 200 ms auf Ihrer Seite? Auch wenn es passiert, kommt es wieder zu Punkt 1
  3. wie groß sind deine Bilder? Sogar ein langsamer Server kann pro Sekunde einige Dutzend 3-Kb-Dateien liefern. Wenn Ihre Website größere Bilder enthält, sollten Sie die Verwendung von Bildern mit niedriger Auflösung und hoher Auflösung in Betracht ziehen, z. B. mit lightBox .

Computerprobleme sind oft nur Designprobleme.

** EDIT **

Hier ist eine Idee:

  1. ihre Seite sollte DIV-Container mit der Breite und Höhe der erwarteten Bildgröße anzeigen (verwenden Sie CSS zum Style). Fügen Sie in jeder DIV einen Link hinzu. Zum Beispiel :

    <div class="img-wrapper thumbnail">
       <a href="http://www.domain.com/path/to/image">Loading...</a>
    </div>
    
  2. Fügen Sie dieses Javascript hinzu (ungeprüft, die Idee ist selbstbeschreibend)

    $(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();
       }
    };
    
    });
    
17
Yanick Rochon

Nun, meine Idee:

1) initiieren Sie eine AJAX - Anforderung für das Image. Wenn dies gelingt, wird das Image in den Browser-Cache verschoben. Sobald Sie das Attribut 'src' festgelegt haben, wird das Image aus dem Cache angezeigt

2) Sie können das XHR abbrechen

Ich habe einen winzigen Server mit Express geschrieben, der den riesigen Bilddownload emuliert (er wartet eigentlich nur 20 Sekunden und gibt dann ein Bild zurück). Dann habe ich das in meinem 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>
12
Guard

Sie können Ihre Bilder mit ajax-Aufrufen laden, und für den Fall, dass die Bildlauffunktion verwendet wird, können Sie die Anrufe abbrechen.
In jQuery-Pseudo-Code wäre das ungefähr so ​​(verzeihen Sie mir Fehler in der Syntax, es ist nur ein Beispiel)

1) Markieren Sie Bilder, die Sie laden möchten

$(".image").each( function(){
    if ( is_in_visible_area(this) ) { // check [1] for example
        $(this).addClass("load_me");
    } else {
        $(this).addClass("dont_load");
    }
});

2) Bilder laden

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) Brechen Sie den Ladevorgang aus dem Bildschirm ab

for( id in ajax_requests ) {
    if ( ! is_in_visible_area(id) ) {
        ajax_requests[id].abort();
    }
}

Fügen Sie natürlich auch eine Prüfung hinzu, ob das Bild bereits geladen ist (z. B. Klasse "geladen").

[1]. Überprüfe ob das Element nach dem Scrollen sichtbar ist

[2]. Ajax-Anforderungen mit jQuery abbrechen

2
Jakub M.
  1. Verwenden Sie einen Stack zum Verwalten von Ajax-Anforderungen (bedeutet, dass das Laden seriell statt parallel erfolgt, aber es lohnt sich).

  2. Warten Sie nach dem Scrollen auf 300ms und schieben Sie dann alle Bilder im Ansichtsbereich in den Stapel

  3. Bei jedem Bildlauf eines Benutzers wird geprüft, ob ein Stapel ausgeführt wird. (fyi - Sie können alle Anfragen an eine bestimmte URL anhalten, anstatt alle Ajax-Aufrufe zu beenden. Sie können auch Regex verwenden, damit keine anderen Anfragen auf der Seite angehalten werden.)

  4. Wenn ein vorhandener Stapel ausgeführt wird, platzieren Sie alle darin enthaltenen Bilder mit Ausnahme der obersten.

  5. Bei allen Ajax-Aufrufen - Binden Sie das beforeSend () -Ereignis ein, um das betreffende Bild aus dem Stapel zu entfernen

Es ist jetzt spät, aber wir haben bei der Arbeit etwas sehr Ähnliches getan - wenn Sie den detaillierten Code benötigen, lassen Sie es mich wissen.

Prost!

1
Varun Vohra

Möglicherweise könnten Sie das Bild über ein PHP-Skript bereitstellen, das ein Feld in der Datenbank (oder besser noch ein Memcached) überprüft, das das Laden anhalten würde. Das Skript würde das Bild in Blöcke aufteilen und zwischen jedem Block pausieren und prüfen, ob das Stopp-Flag für die jeweilige Anforderung gesetzt ist. Wenn es gesetzt ist, senden Sie den Header mit A 204 ohne Inhalt, der, sobald er vom Browser empfangen wird, nicht mehr empfangen wird. 

Dies kann jedoch ein wenig über Kill sein.

0
matthewdaniel

Übrigens, eine andere Idee, die funktionieren könnte:

1) Erstellen Sie einen neuen iframe

2) In dem iframe befindet sich das Skript, mit dem das Bild geladen wird. Wenn es geladen ist, rufen Sie die Methode .parent auf

3) Stoppen Sie im Bedarfsfall das Laden des Iframe-Inhalts mithilfe von .stop für das Iframe-Objekt

0
Guard

Die Lösung könnte ein Webworker sein. Ein Webworker kann abgebrochen werden und mit ihm die Verbindung ... Aber es gibt ein kleines Problem, dass der Webworker die begrenzten Verbindungen des Browsers verwendet, sodass die Anwendung blockiert wird.

Ich arbeite gerade an einer Lösung mit serviceWorkers - sie haben kein Verbindungslimit (ich hoffe es)

0
teter