2010-05-11 14 views
17

Me gustaría cancelar una operación .load(), cuando la carga() no vuelve en 5 segundos. Si es así, mostraré un mensaje de error como 'lo siento, no hay imagen cargada'.Cómo cancelar un jquery.load()?

Lo que tengo es ...

... el manejo de tiempo de espera:

jQuery.fn.idle = function(time, postFunction){ 
    var i = $(this); 
    i.queue(function(){ 
     setTimeout(function(){ 
      i.dequeue(); 
      postFunction(); 
     }, time); 
    }); 
    return $(this); 
}; 

... inicialización del mensaje de error de tiempo de espera:

var hasImage = false; 

$('#errorMessage') 
    .idle(5000, function() { 

     if(!hasImage) { 
      // 1. cancel .load()    
      // 2. show error message 
     } 
    }); 

... la cargando imagen:

$('#myImage') 
    .attr('src', '/url/anypath/image.png') 
    .load(function(){ 
     hasImage = true; 
     // do something... 
     }); 

Lo único que no pude entender es cómo cancelar la carga en ejecución() (si es posible).

Editar:

Otra forma: ¿Cómo evito que el método .load() para llamar a su función de devolución de llamada cuando se está volviendo?

Respuesta

10

Si desea un manejo personalizado como este, simplemente no puede usar la función jQuery.load(). Tendrás que actualizar a jQuery.ajax(), que recomiendo de todos modos, ya que puedes hacer mucho más con él, especialmente si necesitas algún tipo de manejo de errores, será necesario.

Utilice la opción beforeSend para jQuery.ajax y capture el xhr. Luego puede crear una devolución de llamada que puede cancelar el xhr después de su tiempo de espera, y las devoluciones de llamadas según sea necesario.

Este código no está probado, pero debería comenzar.

var enableCallbacks = true; 
var timeout = null; 
jQuery.ajax({ 
    .... 
    beforeSend: function(xhr) { 
    timeout = setTimeout(function() { 
     xhr.abort(); 
     enableCallbacks = false; 
     // Handle the timeout 
     ... 
    }, 5000); 
    }, 
    error: function(xhr, textStatus, errorThrown) { 
    clearTimeout(timeout); 
    if (!enableCallbacks) return; 
    // Handle other (non-timeout) errors 
    }, 
    success: function(data, textStatus) { 
    clearTimeout(timeout); 
    if (!enableCallbacks) return; 
    // Handle the result 
    ... 
    } 
}); 
+0

fullware, gracias por su útil respuesta! Hay algo pequeño que corregir: tuve que reemplazar la línea "beforeSend (xhr) {" por "beforeSend: function (xhr) {" – Dirk

2

Creo que lo más simple sería usar $.ajax directamente. De esta forma, puede comenzar un tiempo de espera y, a partir del tiempo de espera, establecer un indicador que el controlador de la llamada ajax puede verificar. El tiempo de espera también puede mostrar un mensaje o lo que sea.

+0

Hi Pointy, gracias por su respuesta. Tuve el mismo pensamiento, pero no quiero romper este buen manejo encapsulado de jQuery ... – Dirk

+0

Bueno, la API '.load()' es sincrónica, y eso es todo. – Pointy

+0

hmm, puedo tener que cambiar mi pregunta a: cómo evito que el método .load() llame a su función de devolución de llamada cuando se devuelve ... – Dirk

1

No creo que se puede llegar desde aquí - como se ha mencionado @Pointy, es necesario que tenga que llegar al objeto XMLHttpRequest para que pueda acceder el método .abort() en él. Para eso, necesitas la API jQuery .ajax() que te devuelve el objeto.

Al no poder cancelar la solicitud, otro método a considerar es agregar conocimiento del tiempo de espera en la función de devolución de llamada. Se podría hacer esto de dos maneras - primero:

var hasImage = false; 

$('#errorMessage') 
    .idle(5000, function() { 

     if(!hasImage) { 
      // 1. cancel .load()    
      // 2. show error message 
      // 3. Add an aborted flag onto the element(s) 
      $('#myImage').data("aborted", true); 
     } 
    }); 

Y su devolución de llamada:

$('#myImage') 
    .attr('src', '/url/anypath/image.png') 
    .load(function(){ 
     if($(this).data("aborted")){ 
      $(this).removeData("aborted"); 
      return; 
     } 
     hasImage = true; 
     // do something... 
     }); 

O puede pasar por alto la inactividad para esta funcionalidad particular:

$('#myImage') 
    .attr('src', '/url/anypath/image.png') 
    .data("start", (new Date()).getTime()) 
    .load(function(){ 
     var start = $(this).data("start"); 
     $(this).removeData("start"); 
     if(((new Date()).getTime() - start) > 5000) 
      return; 

     hasImage = true; 
     // do something... 
     }); 

Ninguno de los enfoques es ideal, pero no creo que pueda cancelar la carga directamente desde jQuery 1.4; sin embargo, podría ser una buena solicitud de funciones para el equipo de jQuery.

+1

+1 Pero el '.attr ('src', '/url/anypath/image.png') 'envía inmediatamente la solicitud HTTP para obtener la imagen, antes de que se registre el evento de carga. Deberías mover el 'attr()' al final, después de 'load()'. –

2

Si se carga el código después de jQuery se ha cargado usted será capaz de llamar .load() con un parámetro de tiempo de espera.

jQuery.fn.load = function(url, params, callback, timeout) { 
    if (typeof url !== "string") { 
     return _load.call(this, url); 

    // Don't do a request if no elements are being requested 
    } else if (!this.length) { 
     return this; 
    } 

    var off = url.indexOf(" "); 
    if (off >= 0) { 
     var selector = url.slice(off, url.length); 
     url = url.slice(0, off); 
    } 

    // Default to a GET request 
    var type = "GET"; 

    // If the second parameter was provided 
    if (params) { 
     // If it's a function 
     if (jQuery.isFunction(params)) { 
      if(callback && typeof callback === "number"){ 
       timeout = callback; 
       callback = params; 
       params = null; 
      }else{ 
       // We assume that it's the callback 
       callback = params; 
       params = null; 
       timeout = 0; 
      } 
     // Otherwise, build a param string 
     } else if(typeof params === "number"){ 
      timeout = params; 
      callback = null; 
      params = null; 
     }else if (typeof params === "object") { 
      params = jQuery.param(params, jQuery.ajaxSettings.traditional); 
      type = "POST"; 
      if(callback && typeof callback === "number"){ 
       timeout = callback; 
       callback = null; 
      }else if(! timeout){ 
       timeout = 0; 
      } 
     } 
    } 

    var self = this; 

    // Request the remote document 
    jQuery.ajax({ 
     url: url, 
     type: type, 
     dataType: "html", 
     data: params, 
     timeout: timeout, 
     complete: function(res, status) { 
      // If successful, inject the HTML into all the matched elements 
      if (status === "success" || status === "notmodified") { 
       // See if a selector was specified 
       self.html(selector ? 
        // Create a dummy div to hold the results 
        jQuery("<div />") 
         // inject the contents of the document in, removing the scripts 
         // to avoid any 'Permission Denied' errors in IE 
         .append(res.responseText.replace(rscript, "")) 

         // Locate the specified elements 
         .find(selector) : 

        // If not, just inject the full result 
        res.responseText); 
      } 

      if (callback) { 
       self.each(callback, [res.responseText, status, res]); 
      } 
     } 
    }); 

    return this; 
}; 

No estoy seguro si usted está interesado en sobreescribir cualquier funciones "estándar" jQuery, pero esto permitirá utilizar .load() la forma en que usted describió.

0

$('#myImage').load(function(){...}) no es una llamada de función para cargar la imagen, en realidad es una abreviatura para vincular una devolución de llamada al onloadevent.

Por lo tanto, agregar un parámetro timeout al .load()method como se sugiere en otras respuestas no tendrá ningún efecto.

Se piensa que sus dos opciones son:

  1. continuar en el camino que está siguiendo y hacer algo como $('#myImage').attr('src', ''); a cancelar la carga de la imagen después de que los tiempos , o

  2. Encuentre alguna forma de usar $.ajax({ ... , timeout: 5000, ...}); para cargar la imagen en lugar de dejar que el navegador lo haga automáticamente a través del <img src="..."> atributo.

3

Su pregunta secundaria reformulado:
¿Cómo se cancela pendientes funciones de devolución, creados usando el método .load()?

Puede cancelar todas las devoluciones de llamada jQuery, mediante el uso de esta opción 'nuclear':

$('#myImage').unbind('load'); 
+0

esto no funciona cuando el elemento dom se crea dinámicamente – PUG

0

Usted simplemente puede establecer un tiempo de espera antes de cargar la imagen, así como pruebas para un error de carga.

function LoadImage(yourImage) { 

    var imageTimer = setTimeout(function() { 
     //image could not be loaded: 
     alert('image load timed out'); 
    }, 10000); //10 seconds 

    $(yourImage).load(function (response, status, xhr) { 
     if (imageTimer) { 

      if (status == 'error') { 
       //image could not be loaded: 
       alert('failed to load image'); 

      } else { 
       //image was loaded: 
       clearTimeout(imageTimer); 
       //display your image... 
      } 

     } 
    }); 

} 
Cuestiones relacionadas