La carga diferida (también conocida como carga asincrónica ) es una técnica utilizada en programación informática , especialmente en diseño y desarrollo web , para diferir la inicialización de un objeto hasta que sea necesario. Puede contribuir a la eficiencia en el funcionamiento del programa si se utiliza adecuada y apropiadamente. Esto lo hace ideal en casos de uso en los que se accede al contenido de la red y los tiempos de inicialización deben mantenerse al mínimo, como en el caso de las páginas web . Por ejemplo, posponer la carga de imágenes en una página web hasta que sean necesarias para verlas puede hacer que la visualización inicial de la página web sea más rápida. Lo opuesto a la carga diferida es la carga ansiosa . [1]
Antes de establecerse como estándar web, los marcos web se utilizaban generalmente para implementar la carga diferida.
Uno de ellos es Angular . Dado que la carga diferida disminuye el ancho de banda y, posteriormente, los recursos del servidor, es un fuerte competidor para implementar en un sitio web, especialmente para mejorar la retención de usuarios al tener menos demoras al cargar la página, lo que también puede mejorar la optimización de motores de búsqueda (SEO). [2]
A continuación se muestra un ejemplo de carga diferida utilizada en Angular, programada en TypeScript de Farata Systems [3]
@ NgModule ({ importaciones : [ BrowserModule , RouterModule . forRoot ([ { ruta : '' , componente : HomeComponent }, { ruta : 'producto' , componente : ProductDetailComponent }, { ruta : 'lujo' , loadChildren : () => importar ( './luxury.module' ). luego ( m => m . LuxuryModule ), datos : { preloadme : true } } ] //, {preloadingStrategy: CustomPreloadingStrategy} ) ], declaraciones : [ AppComponent , HomeComponent , ProductDetailComponent ], proveedores : [{ proporcionar : LocationStrategy , useClass : HashLocationStrategy }, CustomPreloadingStrategy ], arranque : [ AppComponent ] })
Desde 2020, los principales navegadores web han habilitado el manejo nativo de la carga diferida de forma predeterminada. [4] [5]
Esto permite incorporar la carga diferida a una página web agregando atributos HTML .
El loading
atributo admite dos valores lazy
y eager
. [6] Al configurar el valor en lazy
se recuperará el recurso solo cuando sea necesario (como cuando una imagen se desplaza a la vista cuando un usuario se desplaza hacia abajo), mientras que al configurarlo en eager
, el estado predeterminado, el recurso se cargará inmediatamente.
<!-- Estos recursos se cargarán inmediatamente --> < img src = "header_image.jpg" > < img src = "header_image2.jpg" cargando = "ansioso" ><!-- Si bien estos recursos se cargarán de forma diferida --> < img src = "article_image.jpg" alt = "..." cargando = "lazy" > < iframe src = "video-player.html" title = " ..." cargando = "perezoso" >> iframe >
Hay cuatro formas comunes de implementar el patrón de diseño de carga diferida: inicialización diferida ; un proxy virtual ; un fantasma y un poseedor de valor . [7] Cada uno tiene sus propias ventajas y desventajas.
Con la inicialización diferida, el objeto primero se establece en null
.
Siempre que se solicita el objeto, se verifica y, si es así null
, el objeto se crea y se devuelve inmediatamente.
Por ejemplo, la carga diferida de un widget se puede implementar en el lenguaje de programación C# de la siguiente manera:
privado int _myWidgetID ; Widget privado _myWidget = nulo ; Widget público MiWidget { get { if ( _myWidget == null ) { _myWidget = Widget . Cargar ( _myWidgetID ); } devolver _miWidget ; } }
O alternativamente, con el operador de asignación de fusión nula ??=
privado int _myWidgetID ; Widget privado _myWidget = nulo ; Widget público MiWidget { get => _myWidget ??= Widget . Cargar ( _myWidgetID ); }
Este método es el más sencillo de implementar, aunque si null
es un valor de retorno legítimo, puede ser necesario utilizar un objeto marcador de posición para indicar que no se ha inicializado. Si este método se utiliza en una aplicación multiproceso , se debe utilizar la sincronización para evitar condiciones de carrera .
Un proxy virtual es un objeto con la misma interfaz que el objeto real. La primera vez que se llama a uno de sus métodos, carga el objeto real y luego delega.
Un fantasma es el objeto que se va a cargar en un estado parcial. Inicialmente puede contener solo el identificador del objeto, pero carga sus propios datos la primera vez que se accede a una de sus propiedades. Por ejemplo, considere que un usuario está a punto de solicitar contenido a través de un formulario en línea. En el momento de la creación, la única información disponible es el contenido al que se accederá, pero se desconocen la acción y el contenido específicos.
Un ejemplo en PHP :
$userData = array ( "UID" = > uniqid (), "requestTime" => microtime ( verdadero ), "dataType" => "" , "request" => "" );if ( isset ( $_POST [ 'datos' ]) && $userData ) { // ... }
Un contenedor de valor es un objeto genérico que maneja el comportamiento de carga diferida y aparece en lugar de los campos de datos del objeto:
ValueHolder privado <Widget> valueHolder ; Widget público MiWidget => valueHolder . ObtenerValor ();