2011-01-23 29 views
34

Estoy tratando de realizar una llamada Ajax con jQuery que funciona bien. Utilizo el evento de éxito para mostrar los datos. Sin embargo, parece que el éxito se activa tan pronto como se carga el archivo HTML externo. Si hay imágenes grandes, continúan cargando después de que se muestran. ¿Hay alguna manera de mostrar el contenido después de que todo esté completamente cargado? Aquí está el código:jQuery Ajax espere hasta que se carguen todas las imágenes

$('#divajax').html('<br><div style="text-align: center;"><img src="res/ajax-loader.gif"></div>'); 
$.ajax({ 
    cache: false, 
    url: 'ajax/content.php', 
    success: function(data) { 
      $('#divajax').html(data); 
    } 
}); 

Respuesta

39

El plugin que @alex escribió no funcionó para mí por alguna razón ... No pude entender por qué. Pero su código me inspiró a encontrar una solución más liviana que esté funcionando para mí. Utiliza las promesas jquery. Tenga en cuenta que, a diferencia del complemento de @alex, esto no intenta contabilizar las imágenes de fondo en los elementos, solo elementos img.

// Fn to allow an event to fire after all images are loaded 
$.fn.imagesLoaded = function() { 

    // get all the images (excluding those with no src attribute) 
    var $imgs = this.find('img[src!=""]'); 
    // if there's no images, just return an already resolved promise 
    if (!$imgs.length) {return $.Deferred().resolve().promise();} 

    // for each image, add a deferred object to the array which resolves when the image is loaded (or if loading fails) 
    var dfds = []; 
    $imgs.each(function(){ 

     var dfd = $.Deferred(); 
     dfds.push(dfd); 
     var img = new Image(); 
     img.onload = function(){dfd.resolve();} 
     img.onerror = function(){dfd.resolve();} 
     img.src = this.src; 

    }); 

    // return a master promise object which will resolve when all the deferred objects have resolved 
    // IE - when all the images are loaded 
    return $.when.apply($,dfds); 

} 

A continuación, se puede usar algo como esto:

$.ajax({ 
    cache: false, 
    url: 'ajax/content.php', 
    success: function(data) { 
     $('#divajax').html(data).imagesLoaded().then(function(){ 
      // do stuff after images are loaded here 
     }); 
    } 
}); 

Con suerte eso es útil para alguien.

Tenga en cuenta que si utiliza el código anterior, si uno de los errores de imagen (por ejemplo, porque la URL era incorrecta), la promesa se resuelve de todos modos y el error se ignora. Esto podría ser lo que quiera, pero, dependiendo de su situación, podría querer abortar lo que esté haciendo si una imagen no se carga.En cuyo caso podría reemplazar la línea onerror de la siguiente manera:

img.onerror = function(){dfd.reject();} 

y coger el error como este:

$('#divajax').html(data).imagesLoaded().done(function(){ 
    // do stuff after all images are loaded successfully here 
}).fail(function(){ 
    // do stuff if any one of the images fails to load 
}); 
+0

¡Esto funciona genial! Gracias. –

+0

Esto funciona maravillosamente. Gracias. – J82

+0

esto parece que puede crear una pérdida de memoria. Cada vez que realiza una llamada ajax, crea un duplicado de cada imagen en la página en memoria y adjunta un evento a cada nuevo objeto de imagen, manteniendo el objeto de imagen en la memoria después de que la función imagesLoaded termine de ejecutarse. Una vez que se cargan todos los objetos de imagen duplicados, ¿cuándo se eliminan de la memoria? ¿Inmediatamente después de ejecutar la devolución de llamada del evento onload? –

0

ver en el uso .load de jQuery()

que tiene una descripción de:

El evento de carga se envía a un elemento cuando él y toda sub los elementos han sido completamente cargados. Este evento se puede enviar a cualquier elemento asociado a una URL: imágenes, scripts, marcos, iframes y el objeto de la ventana.

+0

la cosa es que no puedo apagar las llamadas asíncronas con la carga y establecer el caché opciones ¿verdad? – robs

10

Puede enlazar algo a los eventos de carga para saber cuando terminan:

$('<img>').bind('load', function() { 
    $(this).appendTo('body'); 
}); 

O usted podría utilizar this plugin.

+1

oh dios, no tienes idea de cuánto me ayudó, estaba buscando una solución por horas ... muchas gracias: D – Linas

+5

.on() aparentemente se recomienda sobre .bind() ahora – UpTheCreek

0
$('#divajax').html('<br><div style="text-align: center;"><img src="res/ajax-loader.gif"></div>').load(function() { 
$.ajax({ 
    cache: false, 
    url: 'ajax/content.php', 
    success: function(data) { 
      $('#divajax').html(data); 
    } 
}); 
}); 
-6

Creo que lo mejor es usar este

$(window).ready(function(){ //load your ajax}) 
+0

Este método es más general, pero ¡Me parece que funciona genial! –

+6

Esto no funcionará, ya que '$ (documento) .ready()' y '$ (ventana) .load()' no se activan después de la solicitud de AJAX. – Andreyco

16

Se podía usar mi plugin de jQuery, waitForImages ...

$.ajax({ 
    cache: false, 
    url: 'ajax/content.php', 
    success: function(data) { 

     $('#divajax').html(data).hide().waitForImages(function() { 
      $(this).show(); 
     }); 

    } 
}); 

Esto cargará las cosas en su elemento, ocultarlo , y luego volver a mostrarlo una vez que los elementos descendientes img se hayan cargado.

+0

unos complementos realmente agradables que resuelven el problema de mampostería – ajreal

+1

@alex, ¿puedo usar esto para agregar también, básicamente, estoy haciendo infinitos desplazamientos y agregando elementos al contenedor existente junto con otras imágenes – kobe

+0

@alex, muchas gracias por su plugin, i dio mi contenedor div en append y funciona perfectamente – kobe

4

esto desencadena en cada carga img separado:

$('img').on('load', function() { 
     // do something 
}); 

i utilizado :

var loaded = 0; 
$('img').on('load', function() { 
    loaded++; 
    if(loaded == $('img').length){ 
     // do something 
    } 
}); 
0

Probar este código Funciona bien.

 
$.ajax({ 
    url: "../api/listings", 
    type: 'GET', 
    success: function (html) { 
     $('#container').append(html); 
     $('#container img').on('load', function(){console.log('images loaded')}); 
    }; 
}); 
1

Puede utilizar imagesloaded plugin que es trabajar con JavaScript y jQuery, trate de usar el interior ajax success función de devolución de llamada en el contenido cargado, y ocultar todo el contenido, mientras que imagesloaded función de devolución de llamada no activa, véase más abajo el código de ejemplo

$.ajax({ 
    cache: false, 
    url: 'ajax/content.php', 
    success: function(data) { 
     var $divajax = $('#divajax').html(data).hide(); 
     $divajax.imagesLoaded(function() { 
      $divajax.show(); 
     }); 

    } 
}); 
0

Tengo un pequeño error cuando el plugin no encuentra imágenes de la solución de Daniel.

Por si acaso alguna otra cosa sale el mismo problema:

Cambio:

// if there's no images, just return an already resolved promise 
if (!$imgs.length) {return $.Deferred.resolve().promise();} 

Para:

// if there's no images, just return an already resolved promise 
    if (!$imgs.length) { 
     var dfd = $.Deferred(); 
     return dfd.resolve().promise(); 
    } 
Cuestiones relacionadas