

Il lazy loading (conosciuto anche come caricamento asincrono) è una tecnica utilizzata nella programmazione informatica, in particolare nel web design e nello sviluppo web, che consiste nel posticipare l'inizializzazione di un oggetto fino al momento in cui diventa effettivamente necessario.
Se utilizzato in modo corretto e appropriato, può contribuire a migliorare l'efficienza e le prestazioni di un programma.
Questa tecnica è particolarmente indicata nei casi in cui si accede a contenuti tramite rete e si desidera ridurre al minimo i tempi di caricamento iniziali, come nel caso delle pagine web.
Ad esempio, posticipare il caricamento delle immagini di una pagina web fino al momento in cui queste diventano necessarie per la visualizzazione può rendere più veloce la visualizzazione iniziale della pagina.
L'opposto del lazy loading è l'eager loading (caricamento anticipato), che prevede invece il caricamento degli oggetti prima che siano effettivamente necessari.
Prima che venisse introdotto come standard web, il lazy loading veniva generalmente implementato attraverso l'utilizzo di framework web.
Uno di questi è Angular. Poiché il lazy loading riduce l'utilizzo della larghezza di banda e, di conseguenza, il consumo di risorse del server, rappresenta una soluzione particolarmente utile da implementare in un sito web.
Questa tecnica è utile soprattutto per migliorare la fidelizzazione degli utenti, riducendo i tempi di attesa durante il caricamento delle pagine. Ciò può contribuire anche a migliorare l'ottimizzazione per i motori di ricerca.
Di seguito viene riportato un esempio di utilizzo del lazy loading in Angular, scritto in TypeScript e realizzato da Farata Systems.
@NgModule({
imports: [ BrowserModule,
RouterModule.forRoot([
{path: '', component: HomeComponent},
{path: 'product', component: ProductDetailComponent},
{path: 'luxury', loadChildren: () => import('./luxury.module').then(m => m. LuxuryModule), data: {preloadme: true} } ]
// , {preloadingStrategy: CustomPreloadingStrategy}
)
],
declarations: [ AppComponent, HomeComponent, ProductDetailComponent],
providers: [{provide: LocationStrategy, useClass: HashLocationStrategy}, CustomPreloadingStrategy],
bootstrap: [ AppComponent ]
})
A partire dal 2020, i principali browser web hanno introdotto il supporto nativo al lazy loading, consentendone la gestione automatica.
Questa funzionalità permette di integrare il lazy loading direttamente in una pagina web attraverso l'aggiunta di attributi HTML.
L'attributo loading supporta due valori: lazy ed eager.
<!-- Queste risorse saranno caricate immediatamente -->
<img src="header_image.jpg">
<img src="header_image2.jpg" loading="eager">
<!-- Queste risorse saranno lazy loaded (non saranno caricate fino al momento in cui diventeranno effettivamente necessarie) -->
<img src="article_image.jpg" alt="..." loading="lazy">
<iframe src="video-player.html" title="..." loading="lazy"></iframe>
Esistono quattro modalità comuni per implementare il design pattern del lazy loading: l'inizializzazione lazy (lazy initialization), il proxy virtuale (virtual proxy), il ghost e il contenitore di valori (value holder).
Ognuna di queste modalità presenta vantaggi e svantaggi specifici.
Con l'inizializzazione lazy, l'oggetto viene inizialmente impostato a null.
Ogni volta che viene richiesto l'accesso all'oggetto, il programma ne verifica l'esistenza. Se il suo valore è null, l'oggetto viene creato immediatamente e restituito.
Ad esempio, il lazy loading di un widget può essere implementato nel linguaggio di programmazione C# nel seguente modo:
private int _myWidgetID;
private Widget _myWidget = null;
public Widget MyWidget
{
get
{
if (_myWidget == null)
{
_myWidget = Widget. Load(_myWidgetID);
}
return _myWidget;
}
}
In alternativa, è possibile utilizzare l'operatore di assegnazione con coalescenza dei valori nulli ??=.
private int _myWidgetID;
private Widget _myWidget = null;
public Widget MyWidget
{
get => _myWidget ??= Widget. Load(_myWidgetID);
}
Questo metodo è il più semplice da implementare. Tuttavia, se null è un valore di ritorno valido, potrebbe essere necessario utilizzare un oggetto segnaposto (placeholder object) per indicare che l'oggetto non è ancora stato inizializzato.
Se questo metodo viene utilizzato in un'applicazione multithread, è necessario implementare meccanismi di sincronizzazione per evitare eventuali condizioni di competizione (race condition).
Un proxy virtuale è un oggetto che presenta la stessa interfaccia dell'oggetto reale.
La prima volta che viene invocato uno dei suoi metodi, il proxy carica l'oggetto reale e successivamente gli delega l'esecuzione della chiamata.
Un ghost è un oggetto che viene caricato in uno stato parziale. Inizialmente può contenere soltanto l'identificativo dell'oggetto, ma carica autonomamente i propri dati la prima volta che viene effettuato l'accesso a una delle sue proprietà.
Ad esempio, si consideri il caso in cui un utente stia per richiedere dei contenuti tramite un modulo online. Al momento della creazione dell'oggetto, l'unica informazione disponibile è che verrà effettuato l'accesso a dei contenuti, mentre non sono ancora noti né l'azione specifica che verrà eseguita né i contenuti richiesti.
Un esempio in PHP:
$userData = array (
"UID" = > uniqid(),
"requestTime" => microtime(true),
"dataType" => "",
"request" => ""
);
if (isset($_POST['data']) && $userData) {
// ...
}
Un value holder è un oggetto generico che gestisce il comportamento di lazy loading e viene utilizzato al posto dei campi dati dell'oggetto originale.
private ValueHolder<Widget> valueHolder;
public Widget MyWidget => valueHolder. GetValue();