Defer Block en Angular
Tags: webdev, angular, español, defer
Published: 2023-10-23 00:10:03


![Defer block Angular](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0rsy0bdqox3ld1oslc57.png)
[Defer Block en Angular](https://www.yeou.dev/articulos/angular-defer-block)
Parte fundamental de la nueva sintaxis de Control Flow en específico las Deferrable Views o (Vistas Diferidas) son una nueva etiqueta, la etiqueta `@defer`, Además de todas las nuevas funcionalidades que podemos aprovechar para que nuestro código sea más legible y que lograr mejores interacciones de manera más fácil y así mejorar la experiencia de usuarios.
 
Podemos pensar en `@defer` como el setTimeout() pero `@defer` nos provee de más opciones y funcionalidades, por ejemplo:

```typescript 

setTimeout(() => {
  console.log("Retrasado por 1 segundo.");
}, "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 

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

```


`@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
<button #trigger class="btn btn-red"> Botón de Acción <button/>
```

### On hover(trigger):

Al hacer hover en la platilla de referencia, precisamente en la referencia de plantilla #triggerHover como por ejemplo:
<button #triggerHover class="btn btn-red hover:bg-red"> Botón de Hover <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 
@defer (when isVisible() && isAuth , prefetch on immediate; prefetch when isDataLoaded()) {
  <componente-grande"/>
} 
@placeholder (minimum 500ms){
  Placeholder content!
}
@loading (minimum 1s; after 100ms){
  Loading...
}
@error {
  Loading failed :( 
}

```
 
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](https://dev.to/macaoblog/el-nuevo-control-flow-en-angular-118g)
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
@for (libro of libros) {
  @defer {
    <componente-grande />
  }
}
```


`@for` dentro de un `@defer`

```typescript
@defer {
@for (libro of libros) {
    <componente-grande />
  }
}
```


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
@defer {
  <componente-grande />
}
```

``` typescript
function defer_for_block {
  return [ () => import('./componente-grande') ]
}
```

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