Podemos pensar en @defer como el setTimeout() pero @defer nos provee de más opciones y funcionalidades, por ejemplo:

typescript
1setTimeout(() => { 2 console.log("Retrasado por 1 segundo."); 3}, "1000");

Set timeout solo funciona en como un delay de componente usando @defer con la novedad de que podemos mostrar un placeholder durante el tiempo que indiquemos en este caso un segundo.

typescript
1@defer(on viewport(myPlaceholder), on timer(1s)) { 2 <app-child /> 3} @placeholder(minimum 1000ms) { 4 <div #myPlaceholder>...</div> 5}

@defer tiene más casos de usos, ya que además se incluye otras etiquetas que son de ayuda y que además son explícitas en su uso, como ser:

  • @placeholder
  • @error
  • @loading

Además de combinaciones porque podemos usar junto a un varios triggers(disparadores):

  • when isVisible
  • on idle
  • on inmediate
  • on interaction(trigger)
  • on timer(time)
  • on hover(trigger)
  • on viewport(container)

When

Es una condición que puede ser usada junto a una variable, una función, un valor que paso por un pipe o etc. Los Observables y AsyncPipes no pueden ser usados por el momento.

On idle:

Este es un comportamiento por defecto y se ejecuta cuando la app esté inactiva.

On immediate:

Este trigger se activa cuando él, témplate(plantilla) se renderiza.

On timer(1s):

Es un trigger basado en setTimeout el cual puede usarse en segundos usando la s o en milisegundos usando ms después de la cantidad.

On interaction():

Al hacer clic en la platilla de referencia, precisamente en la referencia de plantilla #trigger como por ejemplo:

html
1<button #trigger class="btn btn-red">Botón de Acción <button /></button>

On hover(trigger):

Al hacer hover en la platilla de referencia, precisamente en la referencia de plantilla #triggerHover como por ejemplo:

html
1<button #triggerHover class="btn btn-red hover:bg-red"> 2 Botón de Hover <button /> 3</button>

On viewport(contenedor):

Al renderizar el viewport de la referencia #contenedor, por ejemplo la página se está renderizando, por lo que al llegar a la etiqueta #contenedor debe hacer algo o ejecutar una función.

Podemos usarlo todos a la vez simplemente separándolos por una coma de la siguiente manera:

typescript
1@defer (when isVisible() && isAuth , prefetch on immediate; prefetch when isDataLoaded()) { 2 <componente-grande"/> 3} 4@placeholder (minimum 500ms){ 5 Placeholder content! 6} 7@loading (minimum 1s; after 100ms){ 8 Loading... 9} 10@error { 11 Loading failed :( 12}

Por lo que podemos usar un defer que al retornar true que está visible y que esté autenticado isAuth pre cargue inmediatamente cuando la plantilla esté lista y que pre cargue una función específica, la cual será isDataLoaded(); como puedes ver está el bloque @placeholder el cual como su nombre lo indica nos sirve para poner contenido estático, @loading en el cual podemos poner un skeleton loader o css de carga para que visualmente el usuario sepa que se está cargando y el @error podemos utilizarlo para mostrar un mensaje o acciones.

Además, todo esto lo podemos combinar con el nuevo Control Flow y combinarlo con @if, @else, @for anidarlo, usar un @defer y muchas combinaciones más para hacer de la experiencia algo más ameno.

defer y for:

@defer dentro de un @for

typescript
1@for (libro of libros) { 2 @defer { 3 <componente-grande /> 4 } 5}

@for dentro de un @defer

typescript
1@defer { 2@for (libro of libros) { 3 <componente-grande /> 4 } 5}

En el primer ejemplo, por cada libro dentro del @for se creará una embedded view y una embedded view anidada por cada @defer lo que nos dará la cantidad de libros.length _ 2 que serían las embedded views del @for y libros.length en el @defer por lo que podemos asumir que si tenemos 100 libros tendremos 100 _ 2 + 100,

Ahora en el segundo ejemplo solo hay una interacción del @defer por lo que las embedded view serán solo una y las del @for serán libros.legth + 1

Por lo que la decisión dependerá de como queremos resolver o usarlo y si cada uno de libros en el for contienen componentes grandes o queremos agregar interacción al @defer como ser un loading o cualquiera de los ejemplos anteriores.

Bonus

Como esto funciona en el compilador, pues simple:

typescript
1@defer { 2 <componente-grande /> 3}
typescript
1function defer_for_block { 2 return [ () => import('./componente-grande') ] 3}

Esta solo es una de las muchas nuevas funcionalidades que trae el renacimiento de Angular.

Related posts

October 09, 2023

Angular Control Flow Syntax: Goodbye ngIf and ngFor

Ahora en Angular tenemos un nuevo control flow(Control de flujo) con el que le diremos adios al ngIf al ngFor y hasta nunca al ngSwitch.

+ Read Article