Skip to content

Commit a57f3eb

Browse files
authored
Merge branch 'main' into poc/incremental-translation
2 parents fa9c98d + 39376c7 commit a57f3eb

15 files changed

Lines changed: 1835 additions & 425 deletions

File tree

adev-es/src/content/guide/di/debugging-and-troubleshooting-di.en.md

Lines changed: 1015 additions & 0 deletions
Large diffs are not rendered by default.

adev-es/src/content/guide/di/debugging-and-troubleshooting-di.md

Lines changed: 270 additions & 270 deletions
Large diffs are not rendered by default.
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Lazy loading services
2+
3+
IMPORTANT: For lazy loading to work, the service you load must be auto-provided. Decorate it with either `@Injectable({providedIn: 'root'})` or [`@Service()`](guide/di/creating-and-using-services#using-the-service-vs-injectable-decorator). Without auto-provisioning, Angular has no way to construct the service after it loads.
4+
5+
Angular's `injectAsync` function lets you load a service on demand, only when it's actually needed. This is useful when a service depends on a large library or rarely used feature, and you don't want to pay for it on the initial page load.
6+
7+
When you use `injectAsync`, the service's code is split out by your bundler into a separate JavaScript chunk and downloaded the first time you ask for the instance. Once loaded, Angular resolves the service through the regular DI system, so it can still depend on other injectables and behaves like any other singleton.
8+
9+
## Lazily injecting a service
10+
11+
Imagine a `ReportExporter` that depends on a heavy spreadsheet library. Most users open the report; only a few click **Export**. Load the exporter on demand:
12+
13+
```angular-ts
14+
import {Component, injectAsync} from '@angular/core';
15+
16+
@Component({
17+
selector: 'app-report',
18+
template: `<button (click)="export()">Export</button>`,
19+
})
20+
export class Report {
21+
private exporter = injectAsync(() => import('./report-exporter').then((m) => m.ReportExporter));
22+
23+
async export() {
24+
const exporter = await this.exporter();
25+
exporter.export();
26+
}
27+
}
28+
```
29+
30+
The first call to `this.exporter()` triggers the dynamic import and resolves the service from DI. Subsequent calls reuse the same promise, so the chunk is only fetched once.
31+
32+
If the lazy-loaded service is the [default export](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/export#using_the_default_export), pass the dynamic import directly, Angular unwraps the `default` for you:
33+
34+
```ts {header: report-exporter.ts}
35+
@Service()
36+
export default class ReportExporter {
37+
/**/
38+
}
39+
```
40+
41+
```ts {header: report.ts}
42+
private exporter = injectAsync(() => import('./report-exporter'));
43+
```
44+
45+
## Prefetching the dependency
46+
47+
By default, the lazy chunk is only fetched when you invoke the returned function. You can start the download earlier by passing a `prefetch` trigger in the options. A trigger is any function that returns a `Promise`, when it resolves, Angular kicks off the loader.
48+
49+
Angular ships with `onIdle`, a built-in trigger that waits until the browser becomes idle:
50+
51+
```ts
52+
import {Component, injectAsync, onIdle} from '@angular/core';
53+
54+
@Component({
55+
/**/
56+
})
57+
export class Report {
58+
private exporter = injectAsync(() => import('./report-exporter').then((m) => m.ReportExporter), {
59+
prefetch: onIdle,
60+
});
61+
}
62+
```
63+
64+
You can also configure `onIdle` with a maximum wait time so the prefetch always happens within a known window, even on busy pages:
65+
66+
```ts
67+
injectAsync(loader, {prefetch: () => onIdle({timeout: 1_000})});
68+
```
69+
70+
NOTE: Prefetching is opportunistic. If the user invokes the feature before the prefetch fires, Angular still loads the dependency immediately and resolves your `await` as soon as it's ready.
71+
72+
## Provide a custom prefetch trigger
73+
74+
A `PrefetchTrigger` is just a function that returns a promise, the loader runs as soon as the promise resolves. Use this to align prefetching with your own signals, such as a hover or a scheduler tick:
75+
76+
```ts
77+
import {PrefetchTrigger} from '@angular/core';
78+
79+
export function onHover(target: HTMLElement): PrefetchTrigger {
80+
return () =>
81+
new Promise<void>((resolve) => {
82+
target.addEventListener('pointerenter', () => resolve(), {once: true});
83+
});
84+
}
85+
```

adev-es/src/content/guide/di/lazy-loading-services.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
# Lazy loading services
1+
# Lazy loading de servicios
22

3-
IMPORTANT: For lazy loading to work, the service you load must be auto-provided. Decorate it with either `@Injectable({providedIn: 'root'})` or [`@Service()`](guide/di/creating-and-using-services#using-the-service-vs-injectable-decorator). Without auto-provisioning, Angular has no way to construct the service after it loads.
3+
IMPORTANT: Para que el lazy loading funcione, el servicio que cargas debe estar auto-provisto. Decóralo con `@Injectable({providedIn: 'root'})` o con [`@Service()`](guide/di/creating-and-using-services#using-the-service-vs-injectable-decorator). Sin auto-provisión, Angular no tiene forma de construir el servicio después de cargarlo.
44

5-
Angular's `injectAsync` function lets you load a service on demand, only when it's actually needed. This is useful when a service depends on a large library or rarely used feature, and you don't want to pay for it on the initial page load.
5+
La función `injectAsync` de Angular te permite cargar un servicio bajo demanda, solo cuando realmente se necesita. Esto es útil cuando un servicio depende de una biblioteca grande o de una funcionalidad poco usada, y no quieres pagar su costo en la carga inicial de la página.
66

7-
When you use `injectAsync`, the service's code is split out by your bundler into a separate JavaScript chunk and downloaded the first time you ask for the instance. Once loaded, Angular resolves the service through the regular DI system, so it can still depend on other injectables and behaves like any other singleton.
7+
Cuando usas `injectAsync`, tu bundler separa el código del servicio en un chunk de JavaScript independiente que se descarga la primera vez que solicitas la instancia. Una vez cargado, Angular resuelve el servicio a través del sistema de DI habitual, así que puede seguir dependiendo de otros inyectables y se comporta como cualquier otro singleton.
88

9-
## Lazily injecting a service
9+
## Inyectando un servicio de forma diferida {#lazily-injecting-a-service}
1010

11-
Imagine a `ReportExporter` that depends on a heavy spreadsheet library. Most users open the report; only a few click **Export**. Load the exporter on demand:
11+
Imagina un `ReportExporter` que depende de una biblioteca pesada de hojas de cálculo. La mayoría de los usuarios abren el reporte; solo unos pocos hacen clic en **Export**. Carga el exportador bajo demanda:
1212

1313
```angular-ts
1414
import {Component, injectAsync} from '@angular/core';
@@ -27,9 +27,9 @@ export class Report {
2727
}
2828
```
2929

30-
The first call to `this.exporter()` triggers the dynamic import and resolves the service from DI. Subsequent calls reuse the same promise, so the chunk is only fetched once.
30+
La primera llamada a `this.exporter()` dispara la importación dinámica y resuelve el servicio desde DI. Las llamadas siguientes reutilizan la misma promesa, así que el chunk solo se descarga una vez.
3131

32-
If the lazy-loaded service is the [default export](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/export#using_the_default_export), pass the dynamic import directly, Angular unwraps the `default` for you:
32+
Si el servicio cargado con lazy loading es la [exportación por defecto](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/export#using_the_default_export), pasa la importación dinámica directamente; Angular extrae el `default` por ti:
3333

3434
```ts {header: report-exporter.ts}
3535
@Service()
@@ -42,11 +42,11 @@ export default class ReportExporter {
4242
private exporter = injectAsync(() => import('./report-exporter'));
4343
```
4444

45-
## Prefetching the dependency
45+
## Precargando la dependencia {#prefetching-the-dependency}
4646

47-
By default, the lazy chunk is only fetched when you invoke the returned function. You can start the download earlier by passing a `prefetch` trigger in the options. A trigger is any function that returns a `Promise`, when it resolves, Angular kicks off the loader.
47+
Por defecto, el chunk diferido solo se descarga cuando invocas la función devuelta. Puedes iniciar la descarga antes pasando un disparador `prefetch` en las opciones. Un disparador es cualquier función que devuelve una `Promise`; cuando esta se resuelve, Angular pone en marcha el cargador.
4848

49-
Angular ships with `onIdle`, a built-in trigger that waits until the browser becomes idle:
49+
Angular incluye `onIdle`, un disparador integrado que espera hasta que el navegador queda inactivo:
5050

5151
```ts
5252
import {Component, injectAsync, onIdle} from '@angular/core';
@@ -61,17 +61,17 @@ export class Report {
6161
}
6262
```
6363

64-
You can also configure `onIdle` with a maximum wait time so the prefetch always happens within a known window, even on busy pages:
64+
También puedes configurar `onIdle` con un tiempo máximo de espera para que la precarga siempre ocurra dentro de una ventana conocida, incluso en páginas con mucha actividad:
6565

6666
```ts
6767
injectAsync(loader, {prefetch: () => onIdle({timeout: 1_000})});
6868
```
6969

70-
NOTE: Prefetching is opportunistic. If the user invokes the feature before the prefetch fires, Angular still loads the dependency immediately and resolves your `await` as soon as it's ready.
70+
NOTE: La precarga es oportunista. Si el usuario invoca la funcionalidad antes de que se dispare la precarga, Angular carga la dependencia inmediatamente de todos modos y resuelve tu `await` en cuanto está lista.
7171

72-
## Provide a custom prefetch trigger
72+
## Proveer un disparador de precarga personalizado {#provide-a-custom-prefetch-trigger}
7373

74-
A `PrefetchTrigger` is just a function that returns a promise, the loader runs as soon as the promise resolves. Use this to align prefetching with your own signals, such as a hover or a scheduler tick:
74+
Un `PrefetchTrigger` es simplemente una función que devuelve una promesa; el cargador se ejecuta en cuanto la promesa se resuelve. Úsalo para alinear la precarga con tus propios eventos, como un hover o un tick de un planificador:
7575

7676
```ts
7777
import {PrefetchTrigger} from '@angular/core';
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Debouncing signals with `debounced`
2+
3+
IMPORTANT: `debounced` is [experimental](reference/releases#experimental). It's ready for you to try, but it might change before it is stable.
4+
5+
Use `debounced` to delay reacting to a signal's value until it stops changing. It returns a `Resource` whose value reflects the debounced value of the source signal.
6+
7+
```angular-ts
8+
import {debounced, resource, signal} from '@angular/core';
9+
10+
@Component({
11+
template: `
12+
<input (input)="query.set($event.target.value)" />
13+
14+
@if (results.isLoading()) {
15+
<p>Searching…</p>
16+
}
17+
@for (item of results.value(); track item.id) {
18+
<li>{{ item.name }}</li>
19+
}
20+
`,
21+
})
22+
export class Search {
23+
query = signal('');
24+
25+
debouncedQuery = debounced(this.query, 300);
26+
27+
results = resource({
28+
params: () => this.debouncedQuery.value(),
29+
loader: ({params}) => fetchResults(params),
30+
});
31+
}
32+
```
33+
34+
`debounced` takes the source signal and a wait duration in milliseconds. The returned resource's `value()` always contains the last settled value, and `status()` tells you whether a new value is still pending.
35+
36+
## Status during debounce
37+
38+
While the debounce timer is counting down, `status()` is `'loading'` and `value()` returns the previously resolved value. When the timer expires, the resource settles to `'resolved'`. If the source signal throws, the resource enters `'error'` immediately; no timer runs.
39+
40+
See [Resource status](/guide/signals/resource#resource-status) for the full list of statuses and their `value()` behavior.
41+
42+
## Custom wait function
43+
44+
Instead of a millisecond duration, you can pass a function that returns a `Promise<void>`. The resource resolves when the promise resolves. If the source signal changes before the promise settles, Angular discards the previous promise and starts a new one.
45+
46+
```ts
47+
debouncedQuery = debounced(query, (value, lastSnapshot) => {
48+
// Retry immediately after an error rather than making the user wait again.
49+
if (lastSnapshot.status === 'error') return;
50+
// Short queries get a longer delay—the user is likely still typing.
51+
const ms = value.length < 3 ? 500 : 200;
52+
return new Promise<void>((resolve) => setTimeout(resolve, ms));
53+
});
54+
```
55+
56+
See the `DebounceTimer` type in the API reference for details.
57+
58+
## Equality
59+
60+
By default, `debounced` uses `Object.is` to compare values.
61+
62+
Provide a custom equality function with the `equal` option when the default identity check is too strict:
63+
64+
```ts
65+
debouncedFilter = debounced(filter, 200, {
66+
equal: (a, b) => a.category === b.category && a.minPrice === b.minPrice,
67+
});
68+
```
69+
70+
## Injection context
71+
72+
`debounced` must be called inside an [injection context](guide/di/dependency-injection-context). Angular automatically destroys the debounced resource and cancels any pending timer when the injector is destroyed.
73+
74+
To use `debounced` outside of an injection context, pass an explicit `Injector` via the options:
75+
76+
```ts
77+
@Service()
78+
export class SearchService {
79+
private injector = inject(Injector);
80+
81+
createDebouncedQuery(query: Signal<string>): Resource<string> {
82+
return debounced(query, 300, {injector: this.injector});
83+
}
84+
}
85+
```

adev-es/src/content/guide/signals/debounced.md

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# Debouncing signals with `debounced`
1+
# Aplicar debounce a signals con `debounced`
22

3-
IMPORTANT: `debounced` is [experimental](reference/releases#experimental). It's ready for you to try, but it might change before it is stable.
3+
IMPORTANT: `debounced` es [experimental](reference/releases#experimental). Está listo para que lo pruebes, pero podría cambiar antes de ser estable.
44

5-
Use `debounced` to delay reacting to a signal's value until it stops changing. It returns a `Resource` whose value reflects the debounced value of the source signal.
5+
Usa `debounced` para retrasar la reacción al valor de una signal hasta que deje de cambiar. Devuelve un `Resource` cuyo valor refleja el valor con debounce de la signal fuente.
66

77
```angular-ts
88
import {debounced, resource, signal} from '@angular/core';
@@ -12,7 +12,7 @@ import {debounced, resource, signal} from '@angular/core';
1212
<input (input)="query.set($event.target.value)" />
1313
1414
@if (results.isLoading()) {
15-
<p>Searching…</p>
15+
<p>Buscando…</p>
1616
}
1717
@for (item of results.value(); track item.id) {
1818
<li>{{ item.name }}</li>
@@ -31,47 +31,47 @@ export class Search {
3131
}
3232
```
3333

34-
`debounced` takes the source signal and a wait duration in milliseconds. The returned resource's `value()` always contains the last settled value, and `status()` tells you whether a new value is still pending.
34+
`debounced` recibe la signal fuente y una duración de espera en milisegundos. El `value()` del resource devuelto siempre contiene el último valor asentado, y `status()` te indica si un nuevo valor sigue pendiente.
3535

36-
## Status during debounce
36+
## Estado durante el debounce {#status-during-debounce}
3737

38-
While the debounce timer is counting down, `status()` is `'loading'` and `value()` returns the previously resolved value. When the timer expires, the resource settles to `'resolved'`. If the source signal throws, the resource enters `'error'` immediately; no timer runs.
38+
Mientras el temporizador del debounce está en cuenta regresiva, `status()` es `'loading'` y `value()` devuelve el valor resuelto anteriormente. Cuando el temporizador expira, el resource se asienta en `'resolved'`. Si la signal fuente lanza un error, el resource entra en `'error'` de inmediato; no se ejecuta ningún temporizador.
3939

40-
See [Resource status](/guide/signals/resource#resource-status) for the full list of statuses and their `value()` behavior.
40+
Consulta [Estado del resource](/guide/signals/resource#resource-status) para ver la lista completa de estados y el comportamiento de `value()` en cada uno.
4141

42-
## Custom wait function
42+
## Función de espera personalizada {#custom-wait-function}
4343

44-
Instead of a millisecond duration, you can pass a function that returns a `Promise<void>`. The resource resolves when the promise resolves. If the source signal changes before the promise settles, Angular discards the previous promise and starts a new one.
44+
En lugar de una duración en milisegundos, puedes pasar una función que devuelva un `Promise<void>`. El resource se resuelve cuando la promesa se resuelve. Si la signal fuente cambia antes de que la promesa se asiente, Angular descarta la promesa anterior e inicia una nueva.
4545

4646
```ts
4747
debouncedQuery = debounced(query, (value, lastSnapshot) => {
48-
// Retry immediately after an error rather than making the user wait again.
48+
// Reintenta de inmediato tras un error en lugar de hacer que el usuario espere de nuevo.
4949
if (lastSnapshot.status === 'error') return;
50-
// Short queries get a longer delay—the user is likely still typing.
50+
// Las consultas cortas reciben un retraso mayor: probablemente el usuario sigue escribiendo.
5151
const ms = value.length < 3 ? 500 : 200;
5252
return new Promise<void>((resolve) => setTimeout(resolve, ms));
5353
});
5454
```
5555

56-
See the `DebounceTimer` type in the API reference for details.
56+
Consulta el tipo `DebounceTimer` en la referencia de la API para más detalles.
5757

58-
## Equality
58+
## Igualdad {#equality}
5959

60-
By default, `debounced` uses `Object.is` to compare values.
60+
Por defecto, `debounced` usa `Object.is` para comparar valores.
6161

62-
Provide a custom equality function with the `equal` option when the default identity check is too strict:
62+
Proporciona una función de igualdad personalizada con la opción `equal` cuando la comprobación de identidad predeterminada sea demasiado estricta:
6363

6464
```ts
6565
debouncedFilter = debounced(filter, 200, {
6666
equal: (a, b) => a.category === b.category && a.minPrice === b.minPrice,
6767
});
6868
```
6969

70-
## Injection context
70+
## Contexto de inyección {#injection-context}
7171

72-
`debounced` must be called inside an [injection context](guide/di/dependency-injection-context). Angular automatically destroys the debounced resource and cancels any pending timer when the injector is destroyed.
72+
`debounced` debe llamarse dentro de un [contexto de inyección](guide/di/dependency-injection-context). Angular destruye automáticamente el resource con debounce y cancela cualquier temporizador pendiente cuando se destruye el inyector.
7373

74-
To use `debounced` outside of an injection context, pass an explicit `Injector` via the options:
74+
Para usar `debounced` fuera de un contexto de inyección, pasa un `Injector` explícito a través de las opciones:
7575

7676
```ts
7777
@Service()

0 commit comments

Comments
 (0)