varios que inyeccion dependencias controladores javascript angular

javascript - controladores - que es inyeccion de dependencias angular



¿Cuál es la mejor manera de inyectar un servicio en otro en angular 2(Beta)? (7)

De alguna manera, @Injectable no funciona para mí en Angular 2.0.0-beta.17 cuando se conecta el Componente A -> Servicio B -> Servicio C.

Tomé este enfoque:

  1. Consulte todos los servicios en el campo de proveedores de @ ComponentA.
  2. En ServiceB, use la anotación @Inject en el constructor para conectar ServiceC.

Ejecute este Plunker para ver un ejemplo o ver el código a continuación

app.ts

@Component({selector: ''my-app'', template: `Hello! This is my app <br/><br/><overview></overview>`, directives: [OverviewComponent] }) class AppComponent {} bootstrap(AppComponent);

overview.ts

import {Component, bind} from ''angular2/core''; import {OverviewService} from "../services/overview-service"; import {PropertiesService} from "../services/properties-service"; @Component({ selector: ''overview'', template: `Overview listing here!`, providers:[OverviewService, PropertiesService] // Include BOTH services! }) export default class OverviewComponent { private propertiesService : OverviewService; constructor( overviewService: OverviewService) { this.propertiesService = overviewService; overviewService.logHello(); } }

overview-service.ts

import {PropertiesService} from "./properties-service"; import {Inject} from ''angular2/core''; export class OverviewService { private propertiesService:PropertiesService; // Using @Inject in constructor constructor(@Inject(PropertiesService) propertiesService:PropertiesService){ this.propertiesService = propertiesService; } logHello(){ console.log("hello"); this.propertiesService.logHi(); } }

propiedades-servicio.ts

// Using @Injectable here doesn''t make a difference export class PropertiesService { logHi(){ console.log("hi"); } }

Sé cómo inyectar un servicio en un componente (a través de @Component), pero ¿cómo puedo usar DI para pasar servicios fuera de los componentes?

En otras palabras, no quiero hacer esto:

export class MyFirstSvc { } export class MySecondSvc { constructor() { this.helpfulService = new MyFirstSvc(); } } export class MyThirdSvc { constructor() { this.helpfulService = new MyFirstSvc(); } }


El servicio se considera compartido entre los componentes. Entonces, digamos que si tengo un servicio, puedo usarlo en diferentes componentes.

Aquí, en esta respuesta, le muestro un servicio que acepta datos de un componente y los envía a otro componente.

He utilizado el concepto de enrutamiento, servicio compartido, objeto compartido. Espero que esto te ayude a entender lo básico del servicio compartido.

Nota: @ Decorater inyectable se utiliza para hacer que el servicio sea inyectable.

Answer

Boot.ts

import {Component,bind} from ''angular2/core''; import {bootstrap} from ''angular2/platform/browser''; import {Router,ROUTER_PROVIDERS,RouteConfig, ROUTER_DIRECTIVES,APP_BASE_HREF,LocationStrategy,RouteParams,ROUTER_BINDINGS} from ''angular2/router''; import {SharedService} from ''src/sharedService''; import {ComponentFirst} from ''src/cone''; import {ComponentTwo} from ''src/ctwo''; @Component({ selector: ''my-app'', directives: [ROUTER_DIRECTIVES], template: ` <h1> Home </h1> <router-outlet></router-outlet> `, }) @RouteConfig([ {path:''/component-first'', name: ''ComponentFirst'', component: ComponentFirst} {path:''/component-two'', name: ''ComponentTwo'', component: ComponentTwo} ]) export class AppComponent implements OnInit { constructor(router:Router) { this.router=router; } ngOnInit() { console.log(''ngOnInit''); this.router.navigate([''/ComponentFirst'']); } } bootstrap(AppComponent, [SharedService, ROUTER_PROVIDERS,bind(APP_BASE_HREF).toValue(location.pathname) ]);

FirstComponent

import {Component,View,bind} from ''angular2/core''; import {SharedService} from ''src/sharedService''; import {Router,ROUTER_PROVIDERS,RouteConfig, ROUTER_DIRECTIVES,APP_BASE_HREF,LocationStrategy,RouteParams,ROUTER_BINDINGS} from ''angular2/router''; @Component({ //selector: ''f'', template: ` <div><input #myVal type="text" > <button (click)="send(myVal.value)">Send</button> `, }) export class ComponentFirst { constructor(service:SharedService,router:Router){ this.service=service; this.router=router; } send(str){ console.log(str); this.service.saveData(str); console.log(''str''); this.router.navigate([''/ComponentTwo'']); } }

Segundo componente

import {Component,View,bind} from ''angular2/core''; import {SharedService} from ''src/sharedService''; import {Router,ROUTER_PROVIDERS,RouteConfig, ROUTER_DIRECTIVES,APP_BASE_HREF,LocationStrategy,RouteParams,ROUTER_BINDINGS} from ''angular2/router''; @Component({ //selector: ''f'', template: ` <h1>{{myName}}</h1> <button (click)="back()">Back<button> `, }) export class ComponentTwo { constructor(router:Router,service:SharedService) { this.router=router; this.service=service; console.log(''cone called''); this.myName=service.getData(); } back() { console.log(''Back called''); this.router.navigate([''/ComponentFirst'']); } }

SharedService y Shared Object

import {Component, Injectable,Input,Output,EventEmitter} from ''angular2/core'' // Name Service export interface myData { name:string; } @Injectable() export class SharedService { sharingData: myData={name:"nyks"}; saveData(str){ console.log(''save data function called'' + str + this.sharingData.name); this.sharingData.name=str; } getData:string() { console.log(''get data function called''); return this.sharingData.name; } }


Lo primero que debe hacer es anotar todos los servicios con la anotación @Injectable . Observe los paréntesis al final de la anotación, sin esto esta solución no funcionará.

Una vez hecho esto, podemos inyectar servicios entre nosotros utilizando la inyección del constructor:

@Injectable() export class MyFirstSvc { } @Injectable() export class MySecondSvc { constructor(helpfulService: MyFirstSvc) { } } @Injectable() export class MyThirdSvc { constructor(helpfulService: MyFirstSvc) { } }


No estoy seguro de si todavía se requiere una respuesta, así que seguiré adelante e intentaré responder.

Considere el siguiente ejemplo donde tenemos un Componente que usa un servicio para completar algunos valores en su plantilla como a continuación

testComponent.component.ts

import { Component } from "@angular/core" import { DataService } from "./data.service" @Component({ selector:"test-component", template:`<ul> <li *ngFor="let person of persons">{{ person.name }}</li> </ul> }) export class TestComponent { persons:<Array>; constructor(private _dataService:DataService){ this.persons = this._dataService.getPersons() } }

El código anterior es bastante simple e intentará obtener lo que getPersons devuelva del DataService. El archivo DataService está disponible a continuación.

data.service.ts

export class DataService { persons:<Array>; constructor(){ this.persons = [ {name: "Apoorv"}, {name: "Bryce"}, {name: "Steve"} ] } getPersons(){ return this.persons }

El código anterior funcionará perfectamente bien sin el uso del decorador inyectable. Pero el problema comenzará cuando nuestro servicio (DataService en este caso) requiera algunas dependencias como por ejemplo. Http. si cambiamos nuestro archivo data.service.ts como se muestra a continuación, obtendremos un error que data.service.ts que no se Cannot resolve all parameters for DataService(?). Make sure they all have valid type or annotations. Cannot resolve all parameters for DataService(?). Make sure they all have valid type or annotations.

import { Http } from ''@angular/http''; export class DataService { persons:<Array>; constructor(){ this.persons = [ {name: "Apoorv"}, {name: "Bryce"}, {name: "Steve"} ] } getPersons(){ return this.persons }

Esto tiene algo que ver con la forma en que funcionan los decoradores en Angular 2. Lea https://blog.thoughtram.io/angular/2015/05/03/the-difference-between-annotations-and-decorators.html para obtener un comprensión profunda de este tema.

El código anterior tampoco funcionará, ya que también tenemos que importar HTTP en nuestro módulo de arranque.

Pero una regla general que puedo sugerir es que si su archivo de servicio necesita una dependencia, entonces debe decorar esa clase con un decorador @Injectable.

referencia: https://blog.thoughtram.io/angular/2015/09/17/resolve-service-dependencies-in-angular-2.html


Primero necesitas brindar tu servicio

Puede proporcionarlo en el método bootstrap:

bootstrap(AppComponent,[MyFirstSvc]);

o en el componente de la aplicación, o en cualquier otro componente, según sus necesidades .:

@Component({ ... providers:[MyFirstSvc] } ...

entonces solo inyecta tu servicio usando el constructor:

export class MySecondSvc { constructor(private myFirstSvc : MyFirstSvc ){} }


Sí, lo primero es agregar el decorador @Injectable en cada servicio que desee inyectar. De hecho, el nombre Injectable es un poco insidioso. No significa que la clase será "inyectable", pero se decorará para poder inyectar los parámetros del constructor. Vea este número de github para más detalles: https://github.com/angular/angular/issues/4404 .

Aquí está mi comprensión del mecanismo de inyección. Al configurar un decorador @Injectable para una clase, Angular intentará crear u obtener instancias para los tipos correspondientes en el inyector para la cadena de ejecución actual. De hecho, no solo hay un inyector para una aplicación Angular2 sino un árbol de inyectores. Están implícitamente asociados a toda la aplicación y componentes. Una característica clave en este nivel es que están vinculados entre sí de forma jerárquica. Este árbol de inyectores mapea el árbol de componentes. No se definen inyectores para "servicios".

Tomemos una muestra. Tengo la siguiente aplicación:

  • Componente AppComponent : el componente principal de mi aplicación que se proporciona al crear la aplicación Angular2 en la función bootstrap

    @Component({ selector: ''my-app'', template: ` <child></child> `, (...) directives: [ ChildComponent ] }) export class AppComponent { }

  • Componente ChildComponent : un subcomponente que se usará dentro del componente AppComponent

    @Component({ selector: ''child'', template: ` {{data | json}}<br/> <a href="#" (click)="getData()">Get data</a> `, (...) }) export class ChildComponent { constructor(service1:Service1) { this.service1 = service1; } getData() { this.data = this.service1.getData(); return false; } }

  • Dos servicios, Service1 y Service2 : Service1 es utilizado por ChildComponent y ChildComponent por Service1

    @Injectable() export class Service1 { constructor(service2:Service2) { this.service2 = service2; } getData() { return this.service2.getData(); } }

    @Injectable() export class Service2 { getData() { return [ { message: ''message1'' }, { message: ''message2'' } ]; } }

Aquí hay una descripción general de todos estos elementos y sus relaciones:

Application | AppComponent | ChildComponent getData() --- Service1 --- Service2

En dicha aplicación, tenemos tres inyectores:

  • El inyector de la aplicación que se puede configurar con el segundo parámetro de la función bootstrap
  • El inyector de AppComponent que se puede configurar utilizando el atributo de providers de este componente. Puede "ver" elementos definidos en el inyector de la aplicación. Esto significa que si no se encuentra un proveedor en este proveedor, se buscará automáticamente en este inyector principal. Si no se encuentra en este último, se generará un error "proveedor no encontrado".
  • El inyector ChildComponent que seguirá las mismas reglas que el AppComponent . Para inyectar elementos involucrados en la cadena de inyección ejecutada para el componente, se buscarán proveedores primero en este inyector, luego en el AppComponent y finalmente en el de aplicación.

Esto significa que cuando intente inyectar el Service1 en el constructor ChildComponent , Angular2 buscará en el inyector ChildComponent , luego en el AppComponent y finalmente en el de la aplicación.

Dado que Service2 debe inyectarse en Service1 , se realizará el mismo procesamiento de resolución: inyector AppComponent , AppComponent one y application one.

Esto significa que tanto Service1 como Service2 pueden especificarse en cada nivel de acuerdo con sus necesidades utilizando el atributo de providers para componentes y el segundo parámetro de la función bootstrap para el inyector de la aplicación.

Esto permite compartir instancias de dependencias para un conjunto de elementos:

  • Si define un proveedor a nivel de aplicación, la instancia creada correspondiente será compartida por toda la aplicación (todos los componentes, todos los servicios, ...).
  • Si define un proveedor a nivel de componente, la instancia será compartida por el componente mismo, sus subcomponentes y todos los "servicios" involucrados en la cadena de dependencia.

Por lo tanto, es muy poderoso y puede organizarse libremente como desee y para sus necesidades.

Aquí está el plunkr correspondiente para que pueda jugar con él: https://plnkr.co/edit/PsySVcX6OKtD3A9TuAEw?p=preview .

Este enlace de la documentación de Angular2 podría ayudarlo: https://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html .

Espero que te ayude (y disculpa la respuesta larga), Thierry


  • "Proporcione" sus servicios en algún lugar en el que desee utilizarlos, por ejemplo, puede colocarlos en la raíz de su aplicación utilizando bootstrap() si solo tiene una instancia de cada servicio (singletons).
  • Use el decorador @Injectable() en cualquier servicio que dependa de otro.
  • Inyecte los otros servicios en el constructor del servicio dependiente.

boot.ts

import {bootstrap} from ''angular2/platform/browser''; import {AppComponent} from ''./app.component''; import {MyFirstSvc} from ''../services/MyFirstSvc''; import {MySecondSvc} from ''../services/MySecondSvc''; bootstrap(AppComponent, [MyFirstSvc, MySecondSvc]);

MySecondSvc.ts

import {Injectable} from ''angular2/core''; import {MyFirstSvc} from ''../services/MyFirstSvc''; @Injectable() export class MySecondSvc { constructor(private _firstSvc:MyFirstSvc) {} getValue() { return this._firstSvc.value; } }

Ver Plunker para otros archivos.

Lo que es un poco extraño sobre Service DI es que todavía depende de los componentes. Por ejemplo, MySecondSvc se crea cuando un componente lo solicita y, dependiendo de dónde se "proporcionó" MyFirstSvc en el árbol de componentes, eso puede afectar qué instancia de MyFirstSvc se inyecta en MySecondSvc . Esto se discute más aquí: ¿solo puede inyectar servicios en los servicios a través de bootstrap?