2011-02-07 20 views
21

sto caricando in modo dinamico (grandi) immagini per disegnare in una tela HTML5, qualcosa di simile:Annullamento di una singola richiesta di immagine nel browser HTML5

var t = new Image(); 
t.onload = ... 
t.src = 'http://myurl'; 

Ma ogni tanto un po 'vorrebbe cancellare l'immagine richiesta completamente.

L'unico modo che mi è venuta è l'impostazione src-''. vale a dire

t.src = '' 

Questo funziona in molti browser, ma sembra che solo Firefox in realtà annulla la richiesta HTTP per l'immagine.

Ho testato questo con Fiddler2 disabilitando la cache e abilitazione "emulare velocità modem". Quindi eseguendo a fiddle to test canceling a image request. (mi piacerebbe sentire altre idee su come testarlo)

So che ci sono modi per cancellare tutte le richieste (as in this question), ma vorrei solo cancellarne una.

Qualsiasi idea su altri modi (in particolare sui browser mobili) per fare questo?

+4

Attenzione a 't.src = ''', la specifica è vaga su cosa dovrebbe accadere. Vedi http://www.nczonline.net/blog/2009/11/30/empty-image-src-can-destroy-your-site/ –

+1

Giusto ... alcuni dei browser stanno facendo richieste all'URL della pagina (o URL base) per provare a caricare l'immagine con 'src = '''. Sotto Firefox, l'impostazione di 't.src = null' annulla anche la richiesta, ma non fa nulla sugli altri. La più recente (attuale) specifica, dice (in alcune situazioni) che [dovrebbe sparare su] (http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1 .html # update-the-image-data) ... kindof. – Amir

+3

L'impostazione di 'src' su un'immagine in linea in Firefox annulla anche la richiesta precedente:' t.src = 'data: image/gif; base64, R0lGOD ... 'guardalo in [questo violino] (http: // jsfiddle. net/amirshim/F4HbT/21 /) – Amir

risposta

13

Questo è l'unico modo in cui sono riuscito a farlo funzionare in tutti i browser moderni (Chrome, Safari, Mobile-Safari, Firefox e IE9).

  • Caricare un vuoto e nascosta iframe
  • aggiungere un image tag alla body nel iframe
  • quando i img.onload Completa, è possibile utilizzare tale elemento immagine dom disegnare ad una tela HTML5 con drawImage()
  • se si desidera annullare il caricamento, immettere stop() su iframe's contentWindow (o execCommand("stop", false) su contentDocument in IE).
  • dopo aver annullato il caricamento di un'immagine, è possibile riutilizzare l'iframe per caricare più immagini.

ho creato una classe per questo, e mettere il codice CoffeeScript (ed è compilato javascript) su github: Cancelable Html5 Image Loader

Se si vuole giocare con lui, ho anche creato una jsfiddle to test it out. Ricorda di avviare Fiddler2 (o qualcosa di simile) per vedere che la richiesta di rete effettiva viene effettivamente cancellata.

+0

+1 grazie per questo hack. Sarebbe bello trovare un modo per fornire qualcosa per la vecchia versione di IE senza canvas, magari con le librerie che aggiungono il supporto canvas su IE. – regilero

+0

@ Amir, come possiamo implementarlo nelle richieste di tile degli openlayer? – Myra

+0

@Amir Ho avuto lo stesso problema e ho provato a replicare il tuo script ma non riesco a far funzionare il metodo iframe.contentWindow.stop(). C'è un modo per dargli un'occhiata? – Ming

4

Puoi provare window.stop() per interrompere tutte le richieste, ma non quelle individuali. In IE, non è window.stop() è document.execCommand ("Stop", false).

Se hai altre cose in corso su richiesta-saggio, poi facendo questo potrebbe interferire con esso. (Seguirai una richiesta per le risorse che desideri ancora, ma è troppo simile a un duro lavoro).


Quindi, se si voleva fermare una singola richiesta per una grande immagine, che cosa si potrebbe fare è caricare l'immagine in un documento all'interno di un iframe nascosto. L'evento onload dell'IFRAME può essere utilizzato per caricare l'immagine nel documento principale, in base alla quale deve essere memorizzata nella cache (presumendo che le direttive di memorizzazione nella cache siano configurate per farlo).

Se l'immagine richiede troppo tempo, allora è possibile accedere contentWindow del IFRAME ed emettere un comando di arresto a quello.

È necessario disporre di tanti elementi IFRAME quante sono le immagini che possono essere richieste contemporaneamente.

+0

"ma non i singoli" ... puoi eseguire il backup? Il resto delle informazioni che hai fornito era già dichiarato e collegato alla domanda. – Amir

+0

È possibile interrompere tutte le richieste in corso per la finestra. Quale mi dà un'idea, veda le informazioni supplementari aggiunte alla mia risposta! –

2

Dubito che ci sia un modo cross-browser per farlo accadere senza hack. Un suggerimento è di creare una richiesta AJAX per uno script sul lato server che restituisce una versione codificata Base64 dell'immagine che è possibile impostare come attributo src. Quindi puoi annullare questa richiesta se decidi di annullare il caricamento dell'immagine. Questo potrebbe essere difficile se si desidera mostrare l'immagine progressivamente comunque.

+1

Ottima idea, ma ci sono un paio di problemi associati a questo. Il primo è che la quantità di dati trasferiti è del 33% in più. (base64: 24 bit -> 32 bit). Quindi (specialmente sui browser mobili), mette molta pressione sulla memoria su javascript, dal momento che i dati devono essere memorizzati come una stringa in JS e quindi ha anche un ulteriore passaggio di base64 che lo decodifica. Per file di grandi dimensioni (200 K +) questo potrebbe fare male. Ma questo potrebbe sicuramente funzionare bene in alcuni scenari. – Amir

+0

Questo è un buon punto. Quando ho avuto l'idea, non pensavo al sovraccarico.Apparentemente c'è stato un certo sforzo nella lettura di file binari usando AJAX http://nagoon97.wordpress.com/2008/04/06/reading-binary-files-using-ajax/. Non l'ho mai provato da solo, ma è possibile farlo e poi disegnare l'immagine usando un ''. –

2

Ho lo stesso problema e ho fatto alcuni test.

Ho effettuato alcuni test con gli iframes e ho avuto qualche successo. Testato su Firefox 3.6 e Chrome. Per i test ho utilizzato 9 immagini di 15Mb. Con img preloading ho ucciso più volte il mio firefox (sì, non molto memoty su questo computer), usando img l'azione "suspend" non impedisce il caricamento dell'immagine se la richiesta è iniziata, con iframe l'azione suspend interrompe davvero il download (come rimuovere l'iframe). Il prossimo passo sarà il test con XMLHttpRequests.Poiché questa versione del mio codice test utilizza il comportamento della cache del braowser dall'URL dell'immagine per impedire un secondo caricamento e questo funziona anche con le richieste Ajax. Ma forse con iframe potrei trovare un modo per recuperare direttamente i dati binari dall'immagine caricata in iframe (con limitazioni sugli stessi URL di dominio).

Questo è il mio codice di prova (veramente veloce su Chrome, può uccidere il tuo firefox con troppa immagini molto grandi):

// jQuery.imageload.shared.list contains an array of oversized images url 
jQuery.each(imglist,function(i,imgsrc) { 

    name = 'imageload-frame'; 
    id = name + "-" + i; 
    // with img it is not possible to suspend, the get is performed even after remove 
    //var loader = jQuery('<img />').attr('name', name).attr('id',id); 
    var loader = jQuery('<iframe />').attr('name', name).attr('id',id); 

    //no cache on GET query taken from jQuery core 
    // as we really want to download each image for these tests 
    var ts = +new Date; 
    // try replacing _= if it is there 
    var ret = imgsrc.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2"); 
    // if nothing was replaced, add timestamp to the end 
    imgsrc = imgsrc + ((ret == imgsrc) ? (imgsrc.match(/\?/) ? "&" : "?") + "_=" + ts : ""); 

    loader.css('display', 'none').appendTo('body'); 
    loader.after(jQuery('<a>') 
      .text(' stop ') 
      .attr('href','#') 
      .click(function(){ 
       loader.remove(); 
       jQuery(this).text(' suspended '); 
      }) 
    ); 

    // start the load - preload 
    loader.attr('src',imgsrc); 

    // when preload is done we provide a way to get img in document 
    loader.load(function() { 
     jQuery(this).next("a:first") 
      .text(" retrieve ").unbind('click') 
      .click(function() { 
       var finalimg = jQuery('<img />'); 
       // browser cache should help us now 
       // but there's maybe a way to get it direclty from the iframe 
       finalimg.attr('src',loader[0].src); 
       finalimg.appendTo('body'); 
      }); 
    }); 
}); 

modificare e qui è fillde per provarlo: http://jsfiddle.net/wPr3x/

+0

Così vicino, ma c'è un problema. Per qualche ragione, quando l'immagine viene caricata nell'iframe, non è immediatamente disponibile nella cache. quindi l'immagine finisce per essere caricata due volte. ecco un violino con cui giocare. http://jsfiddle.net/amirshim/na3UA/ Avvia fiddler2 (su un pc) e guarda come viene richiesta l'immagine due volte. Se si disattiva 'use_unique_name', si vedrà che l'immagine viene memorizzata nella cache dopo la prima volta che viene caricata l'intera pagina. – Amir

+0

Ho creato una nuova domanda per provare a risolvere questo problema: http://stackoverflow.com/questions/4981229/image-not-loading-from-cache-after-its-loaded-in-an-iframe – Amir

+0

sul violino esempio non vedo dove si imposta il callback load() prima di impostare l'attributo src e dopo aver inserito l'iframe. Quindi potresti avere questo evento di caricamento chiamato subito dopo il caricamento di "about: blank" o tale, cioè la sorgente di base iframe vuota. – regilero

Problemi correlati