diff --git a/public/docs/ts/latest/guide/dependency-injection.jade b/public/docs/ts/latest/guide/dependency-injection.jade index d8676e14..456ea5e3 100644 --- a/public/docs/ts/latest/guide/dependency-injection.jade +++ b/public/docs/ts/latest/guide/dependency-injection.jade @@ -7,9 +7,19 @@ block includes Angular has its own dependency injection framework, and we really can't build an Angular application without it. It's used so widely that almost everyone just calls it _DI_. + + + **La inyección de dependencia** es un importante patrón de diseño de aplicación. + Angular tiene su propio framework de inyección de dependencia, y + no se puede construir una aplicación de Angular sin ella. + Es tan usado que casi todos se refieren a ella como _DI_. In this chapter we'll learn what DI is and why we want it. Then we'll learn [how to use it](#angular-di) in an Angular app. + + + En este capítulo se aprenderá qué es DI y por qué es necesaria. + Despues se aprenderá [how to use it](#angulat-di) en una aplicación de Angular. - [Why dependency injection?](#why-dependency-injection) - [Angular dependency injection](#angular-dependency-injection) @@ -18,12 +28,19 @@ block includes - [Summary](#summary) Run the . + + + Pruebe el . .l-main-section#why-di :marked ## Why dependency injection? + + ## ¿Por qué inyección de dependencia? Let's start with the following code. + + Se iniciará con el siguiente código. +makeExample('dependency-injection/ts/app/car/car-no-di.ts', 'car', 'app/car/car.ts (without DI)') @@ -31,10 +48,19 @@ block includes Our `Car` creates everything it needs inside its constructor. What's the problem? The problem is that our `Car` class is brittle, inflexible, and hard to test. + + La clase `Car` crea todo lo que necesita dentro de su constructor. + ¿Cuál es el problema con eso? + El problema es que así la clase `Car` es frágil, inflexible, y difícil de probar. Our `Car` needs an engine and tires. Instead of asking for them, the `Car` constructor instantiates its own copies from the very specific classes `Engine` and `Tires`. + + El auto ahora nececita un motor y neumáticos. En lugar de preguntar por ellos, + el constructor de la clase `Car` instancia sus propias copias desde + las clases `Engine` y `Tires`. + What if the `Engine` class evolves and its constructor requires a parameter? Our `Car` is broken and stays broken until we rewrite it along the lines of @@ -44,52 +70,102 @@ block includes But we'll *have* to start caring because when the definition of `Engine` changes, our `Car` class must change. That makes `Car` brittle. + + ¿Qué pasa si la clase `Engine` evoluciona y su constructor requiere un parámetro? + El auto se desompone y continúa así hasta que se vuelvan a escribir las siguientes líneas + `#{_thisDot}engine = new Engine(theNewParameter)`. + No hay que preocuparse por los parámetros del constructor de la clase `Engine` cuando se escribió por primera vez las clase `Car`. + Realmente no hay que preocuparse por eso ahora. + Pero *se tiene* que empezar a cuidar porque + cuando la definición de la clase `Engine` cambie, la de la clase `Car` debe cambiar. + Esto hace a la clase `Car` frágil. What if we want to put a different brand of tires on our `Car`? Too bad. We're locked into whatever brand the `Tires` class creates. That makes our `Car` inflexible. + + ¿Qué pasa si se quiere poner una marca o neumáticos diferentes al auto? Esto es malo. + Se esta atado a cualquier marca que la clase `Tires` crea. Esto hace a la clase `Car` inflexible. Right now each new car gets its own engine. It can't share an engine with other cars. While that makes sense for an automobile engine, we can think of other dependencies that should be shared, such as the onboard wireless connection to the manufacturer's service center. Our `Car` lacks the flexibility to share services that have been created previously for other consumers. - + + Ahora cada auto nuevo tiene su propio motor. No puede compartir su motor con otros autos. + Mientras esto tiene sentido para un motor de automóvil real, + puede pensarse en otras dependencias que deben ser compartidas como la conexion inalámbrica + a bordo al centro del servicio del fabricante. La clase `Car` carece de flesibilidad. + para compartir servicios que fueron creados previamente por otros consumidores. + When we write tests for our `Car` we're at the mercy of its hidden dependencies. Is it even possible to create a new `Engine` in a test environment? What does `Engine`itself depend upon? What does that dependency depend on? Will a new instance of `Engine` make an asynchronous call to the server? We certainly don't want that going on during our tests. + + Cuando se escriben pruebas para la clase `Car` se queda a merced de lo que sus dependencias esconden. + ¿Es posible entonces crear una nueva clase `Engine` en el ambiente de prueba? + ¿Entonces de qué depende la clase `Engine`? ¿De qué depende esta dependencia? + Una nueva instancia de la clase `Engine` hará una llamada asincrona al servidor? + Desde luego, no se desea que esto suceda durante las pruebas. + + + What if our `Car` should flash a warning signal when tire pressure is low? How do we confirm that it actually does flash a warning if we can't swap in low-pressure tires during the test? + + ¿Qué pasa si el auto debe emitir una señal de advertencia cuando la presión del un neumático es baja? + ¿Como puede confirmarce que realmente no se emitira una advertencia? + ¿Y si no podemos cambiar los neumáticos que tengan la presión baja durante la prueba? We have no control over the car's hidden dependencies. When we can't control the dependencies, a class becomes difficult to test. + + No se tiene un control sobre las dependencias ocultas del auto. + Cuando no se tiene un control sobre las dependencias, una clase se vuelve difícil de probar. How can we make `Car` more robust, flexible, and testable? + + ¿Cómo se puede hacer a la clase `Car` más robusta, flexible y fácil de someter a pruebas? + + That's super easy. We change our `Car` constructor to a version with DI: + + Eso es muy facil. Sólo debe cambiarce el constructor de la clase `Car` a una versión con DI: +makeTabs( - 'dependency-injection/ts/app/car/car.ts, dependency-injection/ts/app/car/car-no-di.ts', - 'car-ctor, car-ctor', - 'app/car/car.ts (excerpt with DI), app/car/car.ts (excerpt without DI)')(format=".") +'dependency-injection/ts/app/car/car.ts, dependency-injection/ts/app/car/car-no-di.ts', +'car-ctor, car-ctor', +'app/car/car.ts (excerpt with DI), app/car/car.ts (excerpt without DI)')(format=".") :marked See what happened? We moved the definition of the dependencies to the constructor. Our `Car` class no longer creates an engine or tires. It just consumes them. + + ¿Se ve lo que ocurrió? Se mudarón la definició de las dependencias al contructor. + Ahora la clase `Car` no crea mas el motor o los neumáticos. + Simplemente las consume. block ctor-syntax .l-sub-section :marked We also leveraged TypeScript's constructor syntax for declaring parameters and properties simultaneously. + + También se aproovecha la sintaxis del contructor de TypeScript para declarar + los parámetros y propiedades al mismo tiempo. + :marked Now we create a car by passing the engine and tires to the constructor. + + Ahora se crea un auto dandole al constructor los neumáticos y el motor. +makeExample('dependency-injection/ts/app/car/car-creations.ts', 'car-ctor-instantiation', '')(format=".") @@ -99,13 +175,24 @@ block ctor-syntax decoupled from the `Car` class itself. We can pass in any kind of engine or tires we like, as long as they conform to the general API requirements of an engine or tires. - + + ¿Qué tan grandioso es eso? + La definicion de las dependencias del motor y los neumaticos estan + desconectadas de la clase `Car`. + Se le puede dar cualquier tipo de motor o neumáticos que se deseen, siempre y cuando + se ajusten a lo requisits genrales de la API de un motor o neumáticos. + If someone extends the `Engine` class, that is not `Car`'s problem. + Si alguien crea una subclase de la clase `Engine`, ya no es problema de la clase `Car`. + .l-sub-section :marked The _consumer_ of `Car` has the problem. The consumer must update the car creation code to something like this: + + El _consumidor_ de la clase `Car` tiene ahora el problema. Este consumidor debe actulizar el código para crear el auto + a algo como lo siguiente: - var stylePattern = { otl: /(new Car.*$)/gm }; +makeExample('dependency-injection/ts/app/car/car-creations.ts', 'car-ctor-instantiation-with-param', '', stylePattern)(format=".") @@ -113,29 +200,53 @@ block ctor-syntax :marked The critical point is this: `Car` itself did not have to change. We'll take care of the consumer's problem soon enough. + + El punto crítico aquí es que: la clase `Car` no debe cambiar. + Se abordará el problema más adelante. :marked The `Car` class is much easier to test because we are in complete control of its dependencies. We can pass mocks to the constructor that do exactly what we want them to do during each test: + + La clase `Car` es mas fácil de probar porque se tiene un completo control + sobre sus dependencias. + Es posible darle al constructor valores que hacen exactamente lo que se desea que hagan + durante cada prueba: + - var stylePattern = { otl: /(new Car.*$)/gm }; +makeExample('dependency-injection/ts/app/car/car-creations.ts', 'car-ctor-instantiation-with-mocks', '', stylePattern)(format=".") :marked **We just learned what dependency injection is**. + + **Hasta este momento se ha aprendido lo que es la inyección de dependencias** It's a coding pattern in which a class receives its dependencies from external sources rather than creating them itself. + + Es un patrón de codificación en el que una clase recibe sus dependencias de fuentes externas + en lugar de crearlas. + Cool! But what about that poor consumer? Anyone who wants a `Car` must now create all three parts: the `Car`, `Engine`, and `Tires`. The `Car` class shed its problems at the consumer's expense. We need something that takes care of assembling these parts for us. + + ¡Genial! Pero, ¿que hay de ese probre consumidor? + Cualquiera que quiera un auto debe + crear las tres partes: el auto, el motor y los neumáticos. + La clase `Car` resolvió sus problemas a costa del consumidor. + Ahora se necesita algo que se encargue de ensamblar todas estas piezas. + We could write a giant class to do that: + + Puede escribirse una clase que haga eso: +makeExample('dependency-injection/ts/app/car/car-factory.ts', null, 'app/car/car-factory.ts') @@ -144,15 +255,33 @@ block ctor-syntax But maintaining it will be hairy as the application grows. This factory is going to become a huge spiderweb of interdependent factory methods! + + No es tan malo ahora solo con tres métodos de creación. + Pero el manteniemiento se volverá enredado tan pronto la aplicación crezca. + Esta fabrica se convertirá en una gran telaraña de + métodos de fabrica interdependientes. + + Wouldn't it be nice if we could simply list the things we want to build without having to define which dependency gets injected into what? + + ¿No seria mejor si simplemente se proporcionara una lista de las cosas que se desean construir sin + tener que definir que dependencia debe inyectarce en dónde? + + This is where the dependency injection framework comes into play. Imagine the framework had something called an _injector_. We register some classes with this injector, and it figures out how to create them. + + Es aquí donde entra al juego el framwork de inyección de dependencias. + Imagine que el framework tiene algo llamado _inyector_. + Se regitran entonces algunas clases con este inyecotr, y el interpreta cómo crearlas. When we need a `Car`, we simply ask the injector to get it for us and we're good to go. + + Cuando se necesita un auto, simplemente se solicita al inyector que lo consiga. +makeExample('dependency-injection/ts/app/car/car-injector.ts','injector-call')(format=".") @@ -161,41 +290,68 @@ block ctor-syntax The consumer knows nothing about creating a `Car`. We don't have a gigantic factory class to maintain. Both `Car` and consumer simply ask for what they need and the injector delivers. + + Todo el mundo gana. El auto no sabe nada sobre lo que tenga que ver con la creación del motor o los neumáticos. + El consumidor no sabe nada sobre la creacion del auto. + No se tendrá una enorme clase fabrica que mantener. + Ambos, auto y consumidor simplemente solicitan lo que necesitan y el inyector lo entrega. This is what a **dependency injection framework** is all about. + + Esto es de lo que se trata un **framework de inyección de dependencias**. Now that we know what dependency injection is and appreciate its benefits, let's see how it is implemented in Angular. + + Ahora que se sabe lo que es la inyección de dependencias y cuales son sus beneficios, + se vera como es que Angular lo implementa. .l-main-section#angular-di :marked ## Angular dependency injection + + ## Inyección de dependencias en Angular Angular ships with its own dependency injection framework. This framework can also be used as a standalone module by other applications and frameworks. + + Angular cuenta con su propio framework de inyección de dependencias. Este framework puede también ser usado + como un módulo autónomo por otras aplicaciones y frameworks. + That sounds nice. What does it do for us when building components in Angular? Let's see, one step at a time. + + Eso suena bien. ¿Qué hace Angular en la contrucción de componentes? + Veamoslo, paso a paso. We'll begin with a simplified version of the `HeroesComponent` that we built in the [The Tour of Heroes](../tutorial/). + + Comenzaremos con una versión simplificada de `HeroesComponent` + que fue construida en [The Tour of Heroes](../tutorial/). +makeTabs( - `dependency-injection/ts/app/heroes/heroes.component.1.ts, - dependency-injection/ts/app/heroes/hero-list.component.1.ts, - dependency-injection/ts/app/heroes/hero.ts, - dependency-injection/ts/app/heroes/mock-heroes.ts`, - 'v1,,,', - `app/heroes/heroes.component.ts, - app/heroes/hero-list.component.ts, - app/heroes/hero.ts, - app/heroes/mock-heroes.ts`) +`dependency-injection/ts/app/heroes/heroes.component.1.ts, +dependency-injection/ts/app/heroes/hero-list.component.1.ts, +dependency-injection/ts/app/heroes/hero.ts, +dependency-injection/ts/app/heroes/mock-heroes.ts`, +'v1,,,', +`app/heroes/heroes.component.ts, +app/heroes/hero-list.component.ts, +app/heroes/hero.ts, +app/heroes/mock-heroes.ts`) :marked The `HeroesComponent` is the root component of the *Heroes* feature area. It governs all the child components of this area. Our stripped down version has only one child, `HeroListComponent`, which displays a list of heroes. + + `HeroesComponent` es el componente raíz del área de características *Heroes*. + Y regula todos los componentes hijos de esta área. + La versión simplificada tien on solo hijo, `HeroListComponent`, + que despliega una lista de héroes. :marked Right now `HeroListComponent` gets heroes from `HEROES`, an in-memory collection @@ -204,8 +360,18 @@ block ctor-syntax As soon as we try to test this component or want to get our heroes data from a remote server, we'll have to change the implementation of `heroes` and fix every other use of the `HEROES` mock data. + + Ahora el componente `HeroListComponent` toma la lista de heroes de la coleccioón `HEROES`, + que se encuentra definida en otro archivo. + Eso puede ser suficiente en las primeras etapaas de desarrollo, per esta lejos de ser lo ideal. + Tan pronto como se requiera probar este componente o tomar la información de los datos de los heroes de un servidor remoto, + se tendría que cambiar la implementación de `heroes` y + establecer cada uso en la simulación de datos `HEROES`. + Let's make a service that hides how we get hero data. + + Hagamos un servicio que oculte como se obtienen los datos de un héroe .l-sub-section :marked @@ -213,19 +379,32 @@ block ctor-syntax [separate concern](https://en.wikipedia.org/wiki/Separation_of_concerns), we suggest that you write the service code in its own file. + + Dado que el servicio es un + [separate concern](https://en.wikipedia.org/wiki/Separation_of_concerns), + una sugerencia es + que se escriba el código del servicio en su propio archivo. +ifDocsFor('ts') :marked See [this note](#one-class-per-file) for details. + + Ver [this note](#one-class-per-file) para más detalles. +makeExample('dependency-injection/ts/app/heroes/hero.service.1.ts',null, 'app/heroes/hero.service.ts' ) :marked Our `HeroService` exposes a `getHeroes` method that returns the same mock data as before, but none of its consumers need to know that. + + El servicio `HeroService` proporcionael método `getHeroes` que regresa + la misma simulación de datos anterior, pero niguno de sus consumidores necesita saberlo. .l-sub-section :marked Notice the `@Injectable()` #{_decorator} above the service class. We'll discuss its purpose [shortly](#injectable). + + Observece `@Injectable()` #{_decorator} de debajo de clase service + Se discutira más adelante [shortly](#injectable). - var _perhaps = _docsFor == 'dart' ? '' : 'perhaps'; .l-sub-section @@ -235,17 +414,31 @@ block ctor-syntax asynchronous, #{_perhaps} returning a !{_PromiseLinked}. We'd also have to rewrite the way components consume our service. This is important in general, but not to our current story. + + No se esta pretendiendo que este es un verdadero servicio. + Si realmente se estuvieran tomando datos desde un servidor remoto, la API tendría que ser + asíncrona, #{_perhaps} regresa un !{_PromiseLinked}. + También se tendría que volver a escribir la forma en la que los componentes consumen el servicio. + En general esa es una parte importante, pero no para este pequeño ejemplo. :marked A service is nothing more than a class in Angular 2. It remains nothing more than a class until we register it with an Angular injector. + + Un servicio no es más que una clase en Angular 2. + Sigue siendo una clase hasta que se registra en el inyector de Angular. #bootstrap :marked ### Configuring the injector + + ### Configurando el inyector. We don't have to create an Angular injector. Angular creates an application-wide injector for us during the bootstrap process. + + No es necesario crear un inyector de Angular. + Angular crea una aplicación a escala como inyector duranto los procesos que ejecuta bootstrap. +makeExample('dependency-injection/ts/app/main.ts', 'bootstrap', 'app/main.ts (excerpt)')(format='.') @@ -253,11 +446,21 @@ block ctor-syntax We do have to configure the injector by registering the **providers** that create the services our application requires. We'll explain what [providers](#providers) are later in this chapter. + + Sólo debe confugurrce el inyector registrando a los **proveedores** + que crean los servicio que la aplicación requiere. + Explicaremos que son [providers](#providers) más tarde en este capítulo. We can either register a provider within an [NgModule](ngmodule.html) or in application components + Se puede registra un proveedor ya sea en un [NgModule](ngmodule.html) o en los componenetes de la aplicación ### Registering providers in an NgModule + Here's our AppModule where we register a `Logger`, an `UserService`, and an `APP_CONFIG` provider. + + ### Registrar proveedores en un NgModule + + A continuación se tiene el módulo AppModule donde se registró un `Logger`, un `UserService`, y el proveedor `APP_CONFIG` - var stylePattern = { otl: /(providers)/ }; +makeExample('dependency-injection/ts/app/app.module.ts', 'ngmodule','app/app.module.ts', stylePattern)(format='.') @@ -268,6 +471,9 @@ block ctor-syntax :marked ### Registering providers in a component Here's a revised `HeroesComponent` that registers the `HeroService`. + + ## Registrar proveedores en un componente + A continuación se muestra un ejemplo del componente `HeroesComponent`, el cual registra el servicio `HeroService`. +makeExample('dependency-injection/ts/app/heroes/heroes.component.1.ts', 'full','app/heroes/heroes.component.ts', stylePattern)(format='.') @@ -275,36 +481,57 @@ block ctor-syntax ### When to use the NgModule and when an application component? On the one hand, a provider in an NgModule is registered in the root injector. That means that every provider registered within an NgModule will be accessible in the entire application. + + ### ¿Cuando debe usarse el ngModule y cuándo un componene de aplicación? + Por una parte, un proveedor en el ngModule se registra en el inyector raiz. Esto quiere decir que cada proveedor + registrado dentro de el ngModule sera accecible en toda la aplicación. On the other hand, a provider registered in an application component is available only on that component and all its children. + + Por otro lado, un proveedor que es registrado en un componente de aplicación está disponible para ese componente y sus hijos. We want the `APP_CONFIG` service to be available all across the application, but a `HeroService` is only used within the *Heroes* feature area — and nowhere else. — + + Se requiere que el servicio `APP_CONFIG` este disponible en toda la aplicación, pero el servicio `HeroService` solo es usado + dentro del área de configuración *Heroes* — y en ninguna otra parte. — .l-sub-section :marked Read also **Should I add app-wide providers to the root `AppModule` or the root `AppComponent`?** in the [NgModule FAQ](../cookbook/ngmodule-faq.html#!#q-root-component-or-module) chapter. - + + Puede leer también **¿Debe agregarc proveedores en el módulo raíz `AppModule` o en el componente raís `AppComponent`?** en el capítulo [NgModule FAQ](../cookbook/ngmodule-faq.html#!#q-root-component-or-module) :marked ### Preparing the HeroListComponent for injection + + ### Preparar al componente HeroListComponent para la inyeccion The `HeroListComponent` should get heroes from the injected `HeroService`. Per the dependency injection pattern, the component must ask for the service in its constructor, [as we explained earlier](#ctor-injection). It's a small change: + + El componente `HeroListComponent` debe obtener a los heroes desde el servicio `HeroService` previamente inyectado. + De cuerdo al patrón de inyección de dependencias, el componete debe solicitar el servicio dentro de + su constructor, [as we explained earlier](#ctor-injection). + Es un pequeño cambio: +makeTabs( - `dependency-injection/ts/app/heroes/hero-list.component.2.ts, - dependency-injection/ts/app/heroes/hero-list.component.1.ts`, - null, - `app/heroes/hero-list.component (with DI), - app/heroes/hero-list.component (without DI)`) +`dependency-injection/ts/app/heroes/hero-list.component.2.ts, +dependency-injection/ts/app/heroes/hero-list.component.1.ts`, +null, +`app/heroes/hero-list.component (with DI), +app/heroes/hero-list.component (without DI)`) .l-sub-section :marked #### Focus on the constructor + + #### Atención en el contructor Adding a parameter to the constructor isn't all that's happening here. + + Graegar un parametro al constructor no es el único cambio. +makeExample('dependency-injection/ts/app/heroes/hero-list.component.2.ts', 'ctor')(format=".") @@ -314,19 +541,36 @@ block ctor-syntax (scroll up to confirm that fact). Also recall that the parent component (`HeroesComponent`) has `providers` information for `HeroService`. + + Notar que el parametro que se le pasa al contructor es del tipo `HeroService`, y que + la clase `HeroListComponent` tiene un `@Component` #{_decorator} + (scroll up to confirm that fact). + También hay que recordar que el componente padre (`HeroesComponent`) + tiene la informacion de los proveedores del servicio `HeroService`. The constructor parameter type, the `@Component` #{_decorator}, and the parent's `providers` information combine to tell the Angular injector to inject an instance of `HeroService` whenever it creates a new `HeroListComponent`. + + El tipo de dato del parametro del controlador el decorador `@Component` #{_decorator}, + y la informacion de los proveedores padres se combinan para decirle a + el inyector de Angular que inyecte una instacia de + el servicio `HeroService` donde sea que halla creado una nueva instancia de la clase `HeroListComponent`. #di-metadata :marked ### Implicit injector creation + + ### Crear el inyector implicitamente. When we introduced the idea of an injector above, we showed how to use it to create a new `Car`. Here we also show how such an injector would be explicitly created: + + Anteriormente cuando se introdujo la idea de usar un inyector, se mostró como + usarlo para crear un auto. Ahora se verá como se crea exatamente un inyector + de manera explícita: +makeExample('dependency-injection/ts/app/car/car-injector.ts','injector-create-and-call')(format=".") @@ -337,55 +581,97 @@ block ctor-syntax when it creates components for us — whether through HTML markup, as in ``, or after navigating to a component with the [router](./router.html). If we let Angular do its job, we'll enjoy the benefits of automated dependency injection. + + No se encontrará código como ese el ejemplo Visita de los Héroes o en algún otro ejemplo. + Se *puede* escribir el código para el inyector como se observa en [explicitly creates an injector](#explicit-injector) si *debemos*,pero raramente se hace. + Angular se ocupa de crear y llamar a los inyectores. + cuando crea los componentes — ya sea a través de marcado HTML, como por ejemplo en ``, + o despues de ir a un componente con el [router](./router.html). + Si deja hacer su tranajo a Angular, disfrutará de los beneficios de la inyeccioón de dpendencias automática. :marked ### Singleton services + + ### Servicios independientes. Dependencies are singletons within the scope of an injector. In our example, a single `HeroService` instance is shared among the `HeroesComponent` and its `HeroListComponent` children. + + Las dependencias son únicas dentro del alcance de un inyector. + En el ejemplo, una instancia única de `HeroService` es compartida entre `HeroesComponent` y su hijo `HeroListComponent`. However, Angular DI is an hierarchical injection system, which means that nested injectors can create their own service instances. Learn more about that in the [Hierarchical Injectors](./hierarchical-dependency-injection.html) chapter. + + Angular DI es un sistema de inyección jerárquico, + lo que quiere decir que los inyectores que estén anidados pueden crear instancias de sus propios servicios. + Puede saber mas acerca de esto en el capítulo [Hierarchical Injectors](./hierarchical-dependency-injection.html) chapter. + + + :marked ### Testing the component + + ### Probando el componente We emphasized earlier that designing a class for dependency injection makes the class easier to test. Listing dependencies as constructor parameters may be all we need to test application parts effectively. - + + Anteriormente se enfatizó en que diseñar una clase para inyección de dependencias hace a esta clase mas fácil de probar. + Una lista de las dependencias, como por ejemplo los paramétros del constructor puede ser suficiente para probar partes de la aplicación efectivas. + For example, we can create a new `HeroListComponent` with a mock service that we can manipulate under test: + + Por ejemplo,puede crearce una nueva `HeroListComponent` con un servicio simulado que pueda manipularce + durante la prueba: +makeExample('dependency-injection/ts/app/test.component.ts', 'spec')(format='.') .l-sub-section :marked Learn more in [Testing](../testing/index.html). + + Mas acerca de esto en [Testing](../testing/index.html). :marked ### When the service needs a service + + ### Cuando el servicio necesita un servicio. Our `HeroService` is very simple. It doesn't have any dependencies of its own. + + El servicio `HeroService` es muy simple. No tiene ninuguna dependencia propia. What if it had a dependency? What if it reported its activities through a logging service? We'd apply the same *constructor injection* pattern, adding a constructor that takes a `Logger` parameter. + + ¿Qué pasa si se le agrega una dependencia? ¿Qué tal si reporta sus actividades mediane un servicio de logging? + Debe aplicarcele el mismo patrón de *contructor de inyección* + añadiendo un contructor que cuyo parámetro sea de tipo `Logger`. Here is the revision compared to the original. + + A continuación se encuentra esa revisión comparada con la original. +makeTabs( - `dependency-injection/ts/app/heroes/hero.service.2.ts, - dependency-injection/ts/app/heroes/hero.service.1.ts`, - null, - `app/heroes/hero.service (v2), - app/heroes/hero.service (v1)`) +`dependency-injection/ts/app/heroes/hero.service.2.ts, +dependency-injection/ts/app/heroes/hero.service.1.ts`, +null, +`app/heroes/hero.service (v2), +app/heroes/hero.service (v1)`) :marked The constructor now asks for an injected instance of a `Logger` and stores it in a private property called `#{_priv}logger`. We call that property within our `getHeroes` method when anyone asks for heroes. + + Ahora el constructor solicita una instancia inyectada de un `Logger` y lo almacena en una propiedad privada llamada `#{_priv}logger`. + Se llama a esa propiedad dentro del método `getHeroes` cuando cualquiera solicita la lista de héroes. //- FIXME refer to Dart API when that page becomes available. - var injMetaUrl = 'https://angular.io/docs/ts/latest/api/core/index/InjectableMetadata-class.html'; @@ -395,6 +681,12 @@ h3#injectable Why @Injectable()? injector for instantiation. Generally speaking, an injector will report an error when trying to instantiate a class that is not marked as `@Injectable()`. + + **@Injectable()** marca a la clase como disponible para + la inyección cuando se crea una instancia de ella. Generalmente hablando, el inyector reportará un + error cuando trate de crear una intancia de una clase que no este marcada con + `@Injectable()`. + block injectable-not-always-needed-in-ts .l-sub-section @@ -404,12 +696,23 @@ block injectable-not-always-needed-in-ts But we must have it now that our service has an injected dependency. We need it because Angular requires constructor parameter metadata in order to inject a `Logger`. + + Si esto llega a ocurrir, podría haberse omitido `@Injectable()` de la primer + vesión de `HeroService` porque tenía parámetros inyectados. + Pero debe tenerlo ahora que el servicio tiene dependencias inyectadas. + Se necesita porque Angular requiere los metadatos de los parametros del contructor + en order para inyectarlos en el `Logger`. + + .callout.is-helpful header Suggestion: add @Injectable() to every service class :marked We recommend adding `@Injectable()` to every service class, even those that don't have dependencies and, therefore, do not technically require it. Here's why: + + Se recomienda añadir `@Injectable()` a cualquier clase que sea un servicio aunque no tenga dependencias + y técnicamente no la necesite. La razón de esto es porque: ul(style="font-size:inherit") li Future proofing: No need to remember @Injectable() when we add a dependency later. @@ -419,6 +722,10 @@ block injectable-not-always-needed-in-ts Injectors are also responsible for instantiating components like `HeroesComponent`. Why haven't we marked `HeroesComponent` as `@Injectable()`? + + Los inyectores también son responsables de la instanciación de componentes + como `HeroesComponent`. Entonces, ¿Por qué no se marcó a `HeroesComponent` como + `@Injectable()`? We *can* add it if we really want to. It isn't necessary because the `HeroesComponent` is already marked with `@Component`, and this @@ -426,6 +733,13 @@ block injectable-not-always-needed-in-ts is a subtype of InjectableMetadata. It is in fact `InjectableMetadata` #{_decorator}s that identify a class as a target for instantiation by an injector. + + Esto *puede* añadirce si realmente se desea. Pero no es necesario porque el + componente `HeroesComponent` ya está marcado con `@Component`, y este + decorador de clase !{_decorator} (like `@Directive` and `@Pipe`, which we'll learn about later) + es un subtipo de InjectableMetadata. Está + dentro de `InjectableMetadata` #{_decorator}s el cual + identifica a una clase como suceptible para la inyeccion cuando se crea una instancia de la misma. +ifDocsFor('ts') .l-sub-section @@ -433,6 +747,10 @@ block injectable-not-always-needed-in-ts At runtime, injectors can read class metadata in the transpiled JavaScript code and use the constructor parameter type information to determine what things to inject. + + En tiempo de ejecución el inyector puede tomar los metadatos de una clase desde el código de JavaScript + y usar la información del tipo de dato del parámetro del constructor + para determinar que es lo que va a inyectar. Not every JavaScript class has metadata. The TypeScript compiler discards metadata by default. @@ -440,10 +758,22 @@ block injectable-not-always-needed-in-ts (as it should be in the `tsconfig.json`), the compiler adds the metadata to the generated JavaScript for _every class with at least one decorator_. + + No todas clases de JavaScript tienen metadatos. + El compilador de TypeScript descarta a los metadatos por defecto. + Si la propiedad del compilador `emitDecoratorMetadata` es verdadera + (como debe estar en `tsconfig.json`), + el compilador agrega los metadatos que se generaron de JavaScript + para _cada clase con al menos un decorador_. While any decorator will trigger this effect, mark the service class with the InjectableMetadata #{_decorator} to make the intent clear. + + Mientras que cualquier decorador aplicará este hecho, marcar la clase del servicio con + InjectableMetadata #{_decorator} + hace esa intención más clara. + .callout.is-critical header Always include the parentheses @@ -451,16 +781,27 @@ block injectable-not-always-needed-in-ts :marked Always write `@Injectable()`, not just `@Injectable`. Our application will fail mysteriously if we forget the parentheses. + + Simpre debe escribire `@Injectable()`, no solo `@Injectable`. + La aplicacion fallaría aparentemente sin razón si se olvida de poner los paréntesis. .l-main-section#logger-service :marked ## Creating and registering a logger service + + ## Crear i registrar el servicio logger We're injecting a logger into our `HeroService` in two steps: 1. Create the logger service. 1. Register it with the application. + + Se esta inyectando el logger en en servicio `HeroService` en dos pasos: + 1. Crear el servicio logger. + 1. Registrarlo en la aplicación. Our logger service is quite simple: + + El servicio logger es muy simple: +makeExample('dependency-injection/ts/app/logger.service.ts', null, 'app/logger.service.ts') @@ -471,11 +812,18 @@ block real-logger We're likely to need the same logger service everywhere in our application, so we put it in the project's `#{_appDir}` folder, and we register it in the `providers` #{_array} of the metadata for our application module, `AppModule`. + + Es probable que se necesite del servicio logger en toda la aplicacion, + así que se añadirá en la carpeta `#{_appDir}` del proyecto, y + se registra en los proveedores #{_array} para el módulo `AppModule` de la aplicación. + +makeExcerpt('app/providers.component.ts','providers-logger','app/app.module.ts (excerpt)') :marked If we forget to register the logger, Angular throws an exception when it first looks for the logger: + + Si se olvida registrar el servcio logger, Angular produce una excepción cuando busca primero el servicio logger: code-example(format="nocode"). EXCEPTION: No provider for Logger! (HeroListComponent -> HeroService -> Logger) @@ -484,20 +832,39 @@ code-example(format="nocode"). It needed that provider to create a `Logger` to inject into a new `HeroService`, which it needed to create and inject into a new `HeroListComponent`. + + Así es como Angular dice que el inyector de dependencias no puede encontrar un *proveedor* para el logger. + Es necesario ese proveedor para crear una instancia de la clase `Logger` e inyectarlo en un nuevo + `HeroService`, que al mismo tiempo es necesario para + crearlo e inyectarlo en una nueva instancia de `HeroListComponent`. The chain of creations started with the `Logger` provider. *Providers* are the subject of our next section. + + La cadena de creaciones se inició con el proveedor de ` Logger`. Los *proveedores* son el tema de la siguiente sección. + + .l-main-section#providers :marked ## Injector providers + + ## Proveedores del inyector. A provider *provides* the concrete, runtime version of a dependency value. The injector relies on **providers** to create instances of the services that the injector injects into components and other services. + + Un proveedor proporciona la versión concreta , en decir, el tiempo de ejecución de un valor de dependencia. + El inyector se base en los **proveedores** para crear las instancias de los servicios + que el inyector inyecta en los componentes y otros servicios. We must register a service *provider* with the injector, or it won't know how to create the service. + + Debe registrarse el *proveedor* del servicio con el inyector, o este no sabrá como crear el servicio. Earlier we registered the `Logger` service in the `providers` #{_array} of the metadata for the `AppModule` like this: + + Anteriormente se registró el servicio `Logger` en `providers` #{_array} de los metadatos del módulo `AppModule` como sigue: +makeExample('dependency-injection/ts/app/providers.component.ts','providers-logger') @@ -508,22 +875,38 @@ code-example(format="nocode"). There are many ways to *provide* something that #{implements} `Logger`. The `Logger` class itself is an obvious and natural provider. But it's not the only way. + + Hay muchas maneras de *proporcionar* algo que #{implements} el `Logger`. + La clase `Logger` es en sí un proveedor. + Pero esta no es la única forma. We can configure the injector with alternative providers that can deliver #{objectlike} a `Logger`. We could provide a substitute class. #{loggerlike} We could give it a provider that calls a logger factory function. Any of these approaches might be a good choice under the right circumstances. + + El inyector puede configurarse con alternativas de proveedores que entreguen #{objectlike} un `Logger`. + Se puede proporcionar una clase sustituta. #{loggerlike} + Sele puede dar un proveedor que llama a una función de fábrica de logger. + Cualquiera de estas alternativas es una buena elección en las circunstancias correctas. + What matters is that the injector has a provider to go to when it needs a `Logger`. + + Lo que importa es que el inyector tiene un proveedor al cual ir a cuando necesita un `Logger`. //- Dart limitation: the provide function isn't const so it cannot be used in an annotation. - var _andProvideFn = _docsFor == 'dart' ? '' : 'and provide object literal'; #provide :marked ### The *Provider* class !{_andProvideFn} + + ### La clase *proveedor* !{_andProvideFn} :marked We wrote the `providers` #{_array} like this: + + Se escribieron los proveedores #{_array} de la siguiente forma: +makeExample('dependency-injection/ts/app/providers.component.ts','providers-1') @@ -531,6 +914,10 @@ block provider-shorthand :marked This is actually a shorthand expression for a provider registration using a _provider_ object literal with two properties: + + Esto es en realidad una expresión abreviada para un proveedor de registro + utilizando literalmente un objeto _provider_ con dos propiedades : + +makeExample('dependency-injection/ts/app/providers.component.ts','providers-3') @@ -540,18 +927,30 @@ block provider-ctor-args :marked The first is the [token](#token) that serves as the key for both locating a dependency value and registering the provider. + + El primero es el [token](#token) que sirve como clave tanto para la localización de un valor de la dependencia + como para el registro del proveedor. The second is a !{_secondParam}, which we can think of as a *recipe* for creating the dependency value. There are many ways to create dependency values ... and many ways to write a recipe. + El segundo es un !{_secondParam}, + el cual puede concierarse como una *receta* para crear el valor de dependencia. + Existen muchas maneras de crear los valores de dependencia ... y muchas formas de escribir una receta. #class-provider :marked ### Alternative class providers + + ### Proveedores de clase alternativos Occasionally we'll ask a different class to provide the service. The following code tells the injector to return a `BetterLogger` when something asks for the `Logger`. + + De vez en cuando se solicitará una clase diferente para proporcionar el servicio. + El siguiente código indica al inyector + que regrese un `BetterLogger` cuando se le solicita para el `Logger`. +makeExample('dependency-injection/ts/app/providers.component.ts','providers-4') @@ -563,35 +962,62 @@ block dart-diff-const-metadata Maybe an `EvenBetterLogger` could display the user name in the log message. This logger gets the user from the injected `UserService`, which happens also to be injected at the application level. + + ### Proveedor de clase con dependencias + Tal vez la clase `EvenBetterLogger` puede desplegar el nombre del usuario en el mesaje de registro. + Este registro toma al usuario desde el servicio `UserService` inyectado, + que pasa también al ser inyectado a nivel de aplicación. + +makeExample('dependency-injection/ts/app/providers.component.ts','EvenBetterLogger')(format='.') :marked Configure it like we did `BetterLogger`. + + Hay que configurarlo como se hizo en `BetterLogger`. +makeExample('dependency-injection/ts/app/providers.component.ts','providers-5')(format=".") :marked ### Aliased class providers + + ### Alias de los proveedores de clase Suppose an old component depends upon an `OldLogger` class. `OldLogger` has the same interface as the `NewLogger`, but for some reason we can't update the old component to use it. + + Supongamos que un antiguo componente depende de la clase `OldLogger`. + La clase `OldLogger` tiene la misma interfaz que la clase`NewLogger`, pero por alguna razón + no se puede actualizar en antiguo componente para usarla. When the *old* component logs a message with `OldLogger`, we want the singleton instance of `NewLogger` to handle it instead. - + + Cuando el *viejo* componente registra un mensaje con la clase `OldLogger`, + se quiere de la instancia independiete de `NewLogger` para que lo maneje en su lugar. + The dependency injector should inject that singleton instance when a component asks for either the new or the old logger. The `OldLogger` should be an alias for `NewLogger`. + + El inyector de dependencias debe inyectar esa instancia independiente. + cuando un componente lo solicita ya sea para un nuevo o antigui registro. + La clase `OldLogger` debe entonces ser un alias de la clase `NewLogger`. + We certainly do not want two different `NewLogger` instances in our app. Unfortunately, that's what we get if we try to alias `OldLogger` to `NewLogger` with `useClass`. + + Realmente no se desea tener dos instancias diferentes de la clase `NewLogger` en la aplicación. + Desafortunadamente, eso es lo que pasa si se toma como alias la clase `OldLogger` de `NewLogger` con `useClass`. +makeExample('dependency-injection/ts/app/providers.component.ts','providers-6a')(format=".") :marked The solution: alias with the `useExisting` option. + + Solución: crear el alias la opcion de `useExisting`. - var stylePattern = { otl: /(useExisting: \w*)/gm }; +makeExample('dependency-injection/ts/app/providers.component.ts','providers-6b', '', stylePattern)(format=".") @@ -599,9 +1025,13 @@ block dart-diff-const-metadata #value-provider :marked ### Value providers + + ### Proveedores de valor :marked Sometimes it's easier to provide a ready-made object rather than ask the injector to create it from a class. + + A veces es más fácil proporcionar un objeto ya hecho en lugar de pedir al inyector que lo cree a partir de una clase. block dart-diff-const-metadata-ctor //- N/A @@ -611,6 +1041,9 @@ block dart-diff-const-metadata-ctor :marked Then we register a provider with the `useValue` option, which makes this object play the logger role. + + A continuación, se registra un proveedor con la opción ` useValue`, + lo que hace que este objeto desempeñe el papel de registrador. - var stylePattern = { otl: /(useValue: \w*)/gm }; +makeExample('dependency-injection/ts/app/providers.component.ts','providers-7', '', stylePattern)(format=".") @@ -619,53 +1052,95 @@ block dart-diff-const-metadata-ctor See more `useValue` examples in the [Non-class dependencies](#non-class-dependencies) and [OpaqueToken](#opaquetoken) sections. + + Consulte mas ejemplos para `useValue` en las secciones + [dependencias sin clase](#non-class-dependencies) y + [OpaqueToken](#opaquetoken). #factory-provider :marked ### Factory providers + + ### Proveedores de fabricas Sometimes we need to create the dependent value dynamically, based on information we won't have until the last possible moment. Maybe the information changes repeatedly in the course of the browser session. + + En ocasiones es necesario crear el valor de dependencia dinámicamente, + con base en información que no esta disponible si no hasta el último momento. Suppose also that the injectable service has no independent access to the source of this information. + + Supongase también que el servicio inyectable no tiene acceso independiente a la fuente de esta información. This situation calls for a **factory provider**. + + A esto se el conoce como **proveedor de fabricas** Let's illustrate by adding a new business requirement: the HeroService must hide *secret* heroes from normal users. Only authorized users should see secret heroes. + + Ilustremos esto añadiendo una nueva regla de negocio: + el servicio HeroService debe mantener ocultos a los héroes *secretos* de usuarios normales. + Solo los usuarios autorizados pueden ver a estos héroes. Like the `EvenBetterLogger`, the `HeroService` needs a fact about the user. It needs to know if the user is authorized to see secret heroes. That authorization can change during the course of a single application session, as when we log in a different user. + + Como en el `EvenBetterLogger`, el servicio `HeroService` necesita un hecho sobre el usuario. + Necesita saber si e usuario está autorizado para ver a los héroes secretos. + Esta autorización puede cambiar durante el curso de una sola sesión de aplicación , + como cuando se inicia sesión con un usuario diferente . + + Unlike `EvenBetterLogger`, we can't inject the `UserService` into the `HeroService`. The `HeroService` won't have direct access to the user information to decide who is authorized and who is not. + + + A diferencia de `EvenBetterLogger`, no se puede inyectar a el `UserService` dentro del servicio `HeroService`. + El servicio `HeroService` no tendrá acceso directo a la información del usuario para decidir + quién está autorizado y quién no. .l-sub-section :marked Why? We don't know either. Stuff like this happens. + + ¿Por qué? No sabemos tampoco. Cosas como estas suceden . :marked Instead the `HeroService` constructor takes a boolean flag to control display of secret heroes. + + En cambio, el constructor de ` HeroService` lleva una bandera booleana para controlar la visualización de los héroes secretos. +makeExample('dependency-injection/ts/app/heroes/hero.service.ts','internals', 'app/heroes/hero.service.ts (excerpt)')(format='.') :marked We can inject the `Logger`, but we can't inject the boolean `isAuthorized`. We'll have to take over the creation of new instances of this `HeroService` with a factory provider. - + + Puede inyectarce la clase `Logger`, pero no el valor de `isAuthorized`. + Entonces hay que encargarce de la creación de las nuevas instancias de `HeroService` con un proveedor de fabrica. + A factory provider needs a factory function: + + Un proveedor de fabrica necesita de una función de fabrica: +makeExample('dependency-injection/ts/app/heroes/hero.service.provider.ts','factory', 'app/heroes/hero.service.provider.ts (excerpt)')(format='.') :marked Although the `HeroService` has no access to the `UserService`, our factory function does. + + Aunque el servicio `HeroService` no tiene acceso al `UserService`, la función de fábrica si. We inject both the `Logger` and the `UserService` into the factory provider and let the injector pass them along to the factory function: + + Se inyectan tanto el `Logger` como la `UserService` en el proveedor de la fábrica y se deja que el inyector de pase por alto la función de fábrica: +makeExample('dependency-injection/ts/app/heroes/hero.service.provider.ts','provider', 'app/heroes/hero.service.provider.ts (excerpt)')(format='.') @@ -673,10 +1148,16 @@ block dart-diff-const-metadata-ctor :marked The `useFactory` field tells Angular that the provider is a factory function whose implementation is the `heroServiceFactory`. + + El campo `useFactory` le dice a Angular que el proveedor es una función de fábrica + cuya implementación es la clase `heroServiceFactory`. The `deps` property is #{_an} #{_array} of [provider tokens](#token). The `Logger` and `UserService` classes serve as tokens for their own class providers. The injector resolves these tokens and injects the corresponding services into the matching factory function parameters. + + La propiedad `deps` es #{_un} #{_arreglo} de [tokens de proveedor](#token). + Las clases `Logger` y `UserService` sirven como tokens para sus propios proveedores de clase. - var exportedvar = _docsFor == 'dart' ? 'constant' : 'exported variable' - var variable = _docsFor == 'dart' ? 'constant' : 'variable' @@ -684,31 +1165,50 @@ block dart-diff-const-metadata-ctor Notice that we captured the factory provider in #{_an} #{exportedvar}, `heroServiceProvider`. This extra step makes the factory provider reusable. We can register our `HeroService` with this #{variable} wherever we need it. + + Nótese que se camturó al proveedor de fabrica en #{_una} #{variable exportada}, `heroServiceProvider`. + Este paso extra hace al proveedor de fabrica reutilizable. + Puede registrase al servicio `HeroService` con esta #{variable} donde sea que se necesite. In our sample, we need it only in the `HeroesComponent`, where it replaces the previous `HeroService` registration in the metadata `providers` #{_array}. Here we see the new and the old implementation side-by-side: + + En el ejemplo, unicamente es necesario en el componente `HeroesComponent`, + donde se reemplaza el registro anterior de los `proveedores` de los metadatos del `HeroService` #{_array}. + A continuación se presenta la antigua y nueva implementación paso a paso: - var stylePattern = { otl: /(providers.*),$/gm }; +makeTabs( - `dependency-injection/ts/app/heroes/heroes.component.ts, - dependency-injection/ts/app/heroes/heroes.component.1.ts`, - ',full', - `app/heroes/heroes.component (v3), - app/heroes/heroes.component (v2)`, - stylePattern) +`dependency-injection/ts/app/heroes/heroes.component.ts, +dependency-injection/ts/app/heroes/heroes.component.1.ts`, +',full', +`app/heroes/heroes.component (v3), +app/heroes/heroes.component (v2)`, +stylePattern) .l-main-section#token :marked ## Dependency injection tokens + + ## Tokens de inyección de dependencias When we register a provider with an injector, we associate that provider with a dependency injection token. The injector maintains an internal *token-provider* map that it references when asked for a dependency. The token is the key to the map. + + Cuando se registra un proveedor con un inyector, se le asocia ese proveedor con un token de inyeccion de dependencia. + El inyector mantiene internamente un mapa de *provedor de tokens* el cual usa de referencia cuando + se le solicita una dependencia. El token es la clave del mapa. In all previous examples, the dependency value has been a class *instance*, and the class *type* served as its own lookup key. Here we get a `HeroService` directly from the injector by supplying the `HeroService` type as the token: + + En todos los ejemplos anteriores, el valor de dependencia es una *instancia* de la clase, y + el *tipo* de la clase servia como su propia clave de búsqueda. + Aquí esta la implementación del `HeroService` directamente desde el inyector suministrando el tipo `HeroService` como el token: + +makeExample('dependency-injection/ts/app/injector.component.ts','get-hero-service')(format='.') @@ -717,15 +1217,25 @@ block dart-diff-const-metadata-ctor We define a constructor parameter with the `HeroService` class type, and Angular knows to inject the service associated with that `HeroService` class token: + + Se tiene suerte similar cuando se escribe un constructor que requiere una dependencia basada en la clase inyectada. + Se define entonces el parámetro del constructor de tipo `HeroService`, + y asi Angular sabe inyectar el + servicio asiciado con el token de la clase `HeroService`: + +makeExample('dependency-injection/ts/app/heroes/hero-list.component.ts', 'ctor-signature') :marked This is especially convenient when we consider that most dependency values are provided by classes. + + Esto es especialmente conveniente si se tiene en cuenta que la mayoría de los valores de dependencia son proporcionados por las clases. //- TODO: if function injection is useful explain or illustrate why. :marked ### Non-class dependencies + + ### Dependiencias sin clase p | What if the dependency value isn't a class? Sometimes the thing we want to inject is a block non-class-dep-eg @@ -743,48 +1253,78 @@ p :marked We'd like to make this configuration object available for injection. We know we can register an object with a [value provider](#value-provider). + + Se quiere hacer a este objeto de configuración disponible para la inyección. + Sabemos que se puede registrar un objeto con un [proveedor de valores](#value-provider). block what-should-we-use-as-token :marked But what should we use as the token? We don't have a class to serve as a token. There is no `AppConfig` class. + + Pero, ¿qué puede usar como token? + No se tiene una clase que pueda usarse como token. + No hay una clase AppConfig`. .l-sub-section#interface :marked ### TypeScript interfaces aren't valid tokens + + ### Las interfaces de TypeScript no son tokens válidos. The `HERO_DI_CONFIG` constant has an interface, `AppConfig`. Unfortunately, we cannot use a TypeScript interface as a token: + + La constante `HERO_DI_CONFIG` tiene la interface `AppConfig`. Desafortunadamente, no + se puede usar una interface de TypeScript como token: +makeExample('dependency-injection/ts/app/providers.component.ts','providers-9-interface')(format=".") +makeExample('dependency-injection/ts/app/providers.component.ts','provider-9-ctor-interface')(format=".") :marked That seems strange if we're used to dependency injection in strongly typed languages, where an interface is the preferred dependency lookup key. + + Eso parece extraño si se esta acostumbrado a la inyección de dependencias en lenguajes fuertemente tipados, donde + una interfaz es la clave de búsqueda preferida de la dependencia. It's not Angular's fault. An interface is a TypeScript design-time artifact. JavaScript doesn't have interfaces. The TypeScript interface disappears from the generated JavaScript. There is no interface type information left for Angular to find at runtime. + + Pero no es culpade Angular. Una interfaz es un artefacto de diseño de TypeScript. JavaScript no tiene interfaces. + Las interfaces de TypeScript desaparecen del código JavaScript generado. + No queda información sobre el tipo de interfaz que Angular pueda buscar en tiempo de ejecución. //- FIXME simplify once APIs are defined for Dart. - var opaquetoken = _docsFor == 'dart' ? 'OpaqueToken' : 'OpaqueToken' :marked ### OpaqueToken + + ### OpaqueToken One solution to choosing a provider token for non-class dependencies is to define and use an !{opaquetoken}. The definition looks like this: + + Una posible solución para elegir un proveedor de tokens para una dependencia sin clase + es definir un !{opaquetoken}. + Esta definición luce como a continuación se observa: +makeExample('dependency-injection/ts/app/app.config.ts','token')(format='.') :marked We register the dependency provider using the `OpaqueToken` object: + + Se registra el proveedor de dependencias usando el objeto `OpaqueToken`: +makeExample('dependency-injection/ts/app/providers.component.ts','providers-9')(format=".") :marked Now we can inject the configuration object into any constructor that needs it, with the help of an `@Inject` #{_decorator}: + + Ahora puede inyectarse el objeto de configuración dentro de cualquier constructor que se necesite, con + ayuda del un decorador `@Inject` #{_decorator}: +makeExample('dependency-injection/ts/app/app.component.2.ts','ctor')(format=".") @@ -793,21 +1333,35 @@ block what-should-we-use-as-token :marked Although the !{configType} interface plays no role in dependency injection, it supports typing of the configuration object within the class. + + Aunque la !{configType} interfaz no juega ningún papel en la inyección de dependencia, + es compatible con la tipificación del objeto de configuración dentro de la clase . + + block dart-map-alternative :marked Or we can provide and inject the configuration object in an ngModule like `AppModule`. + + O se puede proveer e inyectar el objeto de configuración en un ngModule como en `AppModule`. +makeExcerpt('app/app.module.ts','ngmodule-providers') #optional :marked ## Optional dependencies + + ## Dependencias opcionales Our `HeroService` *requires* a `Logger`, but what if it could get by without a logger? We can tell Angular that the dependency is optional by annotating the constructor argument with `@Optional()`: + + El servicio `HeroService` *requiere* un `Logger`, pero ¿qué sobre lo que puede obtener sin + el logger? + Puede decirle a Angular que esa dependencia es opcionat anotando + en el argumento del constructor el decorador `@Optional()`: +ifDocsFor('ts') +makeExample('dependency-injection/ts/app/providers.component.ts','import-optional', '') @@ -817,48 +1371,86 @@ block dart-map-alternative When using `@Optional()`, our code must be prepared for a null value. If we don't register a logger somewhere up the line, the injector will set the value of `logger` to null. + + Cuando se utiliza `@Optional()`, el código se prepara para recibir un valor nulo. Si no + se regitra un logger en alguna parte de es línea, el inyector cambiará el + valor de `logger` a nulo. .l-main-section :marked ## Summary + + ## Resumen We learned the basics of Angular dependency injection in this chapter. We can register various kinds of providers, and we know how to ask for an injected object (such as a service) by adding a parameter to a constructor. + + Aprendió los conceptos básicos de la inyección de dependencia en Angular en este capítulo. + Puede registrar varios tipos de proveedores, + y sabe como solicitar un objeto inyectados (como un servicio) + añadiendo un parámetro al constructor. Angular dependency injection is more capable than we've described. We can learn more about its advanced features, beginning with its support for nested injectors, in the [Hierarchical Dependency Injection](hierarchical-dependency-injection.html) chapter. + + La inyección de dependencias de Angular es más capaz de lo que se ha descrito. + Puede aprender más sobre sus características avanzadas, comenzando con su soporte para + inyectores anidados, en el capítulo + [Inyección de dependencias jerárquica](hierarchical-dependency-injection.html). + .l-main-section#explicit-injector :marked ## Appendix: Working with injectors directly + + ## Apéndice: Trabajar con inyectores directamente We rarely work directly with an injector, but here's an `InjectorComponent` that does. + + Difícilmete se trabaja directamente con un inyector, pero + a continuación se muestra el componente `InjectorComponent`, que lo hace. +makeExample('dependency-injection/ts/app/injector.component.ts', 'injector', 'app/injector.component.ts') :marked An `Injector` is itself an injectable service. + + Un `Injector` es propiamente un servico inyectable. In this example, Angular injects the component's own `Injector` into the component's constructor. The component then asks the injected injector for the services it wants. + + El este ejemplo, Angular inyecta propio `Injector` del componente dentro del contructor del componente. + Entonces el componente pide al inyector los servicios que requiere. Note that the services themselves are not injected into the component. They are retrieved by calling `injector.get`. + + Note que los servicios propios nose inyectan dentro del componente. + Estos se recuperan llamando a `injector.get`. The `get` method throws an error if it can't resolve the requested service. We can call `get` with a second parameter (the value to return if the service is not found) instead, which we do in one case to retrieve a service (`ROUS`) that isn't registered with this or any ancestor injector. + + El método `get` lanza un error si no puede obtener el servicio solicitado. + Puede llamarse al método `get` con un segundo parámetro (un valor que debe regresar si no encuentra el servicio) + esto se aplica en caso + de que requiera recuperar un servicio (`ROUS`) que no esta registrado en este o cualquier inyector ancestro. .l-sub-section :marked The technique we just described is an example of the [service locator pattern](https://en.wikipedia.org/wiki/Service_locator_pattern). + + La técnica para lo que describimos es un ejemplo de + [patrón de servicio de localización](https://en.wikipedia.org/wiki/Service_locator_pattern). We **avoid** this technique unless we genuinely need it. It encourages a careless grab-bag approach such as we see here. @@ -866,23 +1458,49 @@ block dart-map-alternative We can't know by inspecting the constructor what this class requires or what it will do. It could acquire services from any ancestor component, not just its own. We're forced to spelunk the implementation to discover what it does. + + *Evitamos* esta técnica a menos que realmente sea necesaria. + Se fomenta un enfoque descuidado grab-bag tal como se ve aquí. + Es difícil de explicar, entender y probar. + Inspeccionando el constructor no se puede saber que clase requiere o que hará. + Se podría adquirir servicios de cualquier componente de los antepasados, no sólo de su propio componente. + Esto obliga a especular en la implementación a descubrir que lo hace. + + Framework developers may take this approach when they must acquire services generically and dynamically. + + Los desarrolladores del Framework pueden tomar este enfoque + cuando se deben adquirir los servicios de forma genérica y dinámicamente. + + +ifDocsFor('ts') .l-main-section#one-class-per-file :marked ## Appendix: Why we recommend one class per file + + ## Apéndice: Por qué se recomienda un archivo por clase. Having multiple classes in the same file is confusing and best avoided. Developers expect one class per file. Keep them happy. + + Tener varias clases en el mismo archivo es confuso y es mejor evitarlo. + Los desarrolladores esperan una clase por archivo. Los mantiene felices. + If we scorn this advice and, say, combine our `HeroService` class with the `HeroesComponent` in the same file, **define the component last!** If we define the component before the service, we'll get a runtime null reference error. + + Si se toma en cuenta este consejo, y por ejemplo + combina la clase `HeroService` con el componente `HeroesComponent` en el mismo archivo, + **defina el componente al final** + Si define el componente antes de el servicio, + tendrá un error de referencia nula en tiempo de ejecución. .l-sub-section :marked @@ -890,3 +1508,10 @@ block dart-map-alternative in this [blog post](http://blog.thoughtram.io/angular/2015/09/03/forward-references-in-angular-2.html). But why flirt with trouble? Avoid the problem altogether by defining components and services in separate files. + + En realidad, puede definirse el componente en primer lugar con la ayuda del método `forwardRef()` como se explica + en [blog post](http://blog.thoughtram.io/angular/2015/09/03/forward-references-in-angular-2.html). + Pero, ¿por qué meterse en problemas? + Evite el problema por completo definiendo los componentes y servicios en archivos separados. + +