Angular 2
Servizi e iniezione delle dipendenze
Ricerca…
Servizio di esempio
servizi / my.service.ts
import { Injectable } from '@angular/core'; @Injectable() export class MyService { data: any = [1, 2, 3]; getData() { return this.data; } }
La registrazione del fornitore di servizi nel metodo bootstrap renderà il servizio disponibile a livello globale.
main.ts
import { bootstrap } from '@angular/platform-browser-dynamic'; import { AppComponent } from 'app.component.ts'; import { MyService } from 'services/my.service'; bootstrap(AppComponent, [MyService]);
Nella versione RC5 la registrazione del fornitore di servizi globali può essere effettuata all'interno del file del modulo. Per ottenere una singola istanza del servizio per l'intera applicazione, il servizio deve essere dichiarato nell'elenco dei provider nel modulo ng dell'applicazione. app_module.ts
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { routing, appRoutingProviders } from './app-routes/app.routes'; import { HttpModule} from '@angular/http'; import { AppComponent } from './app.component'; import { MyService } from 'services/my.service'; import { routing } from './app-resources/app-routes/app.routes'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, routing, RouterModule, HttpModule ], providers: [ appRoutingProviders, MyService ], bootstrap: [AppComponent], }) export class AppModule {}
Utilizzo in MyComponent
componenti / my.component.ts
Approccio alternativo per registrare i fornitori di applicazioni nei componenti dell'applicazione. Se aggiungiamo i provider a livello di componente ogni volta che il componente viene reso, creerà una nuova istanza del servizio.
import { Component, OnInit } from '@angular/core'; import { MyService } from '../services/my.service'; @Component({ ... ... providers:[MyService] // }) export class MyComponent implements OnInit { data: any[]; // Creates private variable myService to use, of type MyService constructor(private myService: MyService) { } ngOnInit() { this.data = this.myService.getData(); } }
Esempio con Promise.resolve
servizi / my.service.ts
import { Injectable } from '@angular/core';
@Injectable()
export class MyService {
data: any = [1, 2, 3];
getData() {
return Promise.resolve(this.data);
}
}
getData()
ora agisce come una chiamata REST che crea una Promessa, che viene immediatamente risolta. I risultati possono essere .then()
all'interno di .then()
e possono essere rilevati anche errori. Questa è una buona pratica e una convenzione per i metodi asincroni.
componenti / my.component.ts
import { Component, OnInit } from '@angular/core';
import { MyService } from '../services/my.service';
@Component({...})
export class MyComponent implements OnInit {
data: any[];
// Creates private variable myService to use, of type MyService
constructor(private myService: MyService) { }
ngOnInit() {
// Uses an "arrow" function to set data
this.myService.getData().then(data => this.data = data);
}
}
Test di un servizio
Dato un servizio che può accedere ad un utente:
import 'rxjs/add/operator/toPromise';
import { Http } from '@angular/http';
import { Injectable } from '@angular/core';
interface LoginCredentials {
password: string;
user: string;
}
@Injectable()
export class AuthService {
constructor(private http: Http) { }
async signIn({ user, password }: LoginCredentials) {
const response = await this.http.post('/login', {
password,
user,
}).toPromise();
return response.json();
}
}
Può essere testato in questo modo:
import { ConnectionBackend, Http, HttpModule, Response, ResponseOptions } from '@angular/http';
import { TestBed, async, inject } from '@angular/core/testing';
import { AuthService } from './auth.service';
import { MockBackend } from '@angular/http/testing';
import { MockConnection } from '@angular/http/testing';
describe('AuthService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpModule],
providers: [
AuthService,
Http,
{ provide: ConnectionBackend, useClass: MockBackend },
]
});
});
it('should be created', inject([AuthService], (service: AuthService) => {
expect(service).toBeTruthy();
}));
// Alternative 1
it('should login user if right credentials are passed', async(
inject([AuthService], async (authService) => {
const backend: MockBackend = TestBed.get(ConnectionBackend);
const http: Http = TestBed.get(Http);
backend.connections.subscribe((c: MockConnection) => {
c.mockRespond(
new Response(
new ResponseOptions({
body: {
accessToken: 'abcdef',
},
}),
),
);
});
const result = await authService.signIn({ password: 'ok', user: 'bruno' });
expect(result).toEqual({
accessToken: 'abcdef',
});
}))
);
// Alternative 2
it('should login user if right credentials are passed', async () => {
const backend: MockBackend = TestBed.get(ConnectionBackend);
const http: Http = TestBed.get(Http);
backend.connections.subscribe((c: MockConnection) => {
c.mockRespond(
new Response(
new ResponseOptions({
body: {
accessToken: 'abcdef',
},
}),
),
);
});
const authService: AuthService = TestBed.get(AuthService);
const result = await authService.signIn({ password: 'ok', user: 'bruno' });
expect(result).toEqual({
accessToken: 'abcdef',
});
});
// Alternative 3
it('should login user if right credentials are passed', async (done) => {
const authService: AuthService = TestBed.get(AuthService);
const backend: MockBackend = TestBed.get(ConnectionBackend);
const http: Http = TestBed.get(Http);
backend.connections.subscribe((c: MockConnection) => {
c.mockRespond(
new Response(
new ResponseOptions({
body: {
accessToken: 'abcdef',
},
}),
),
);
});
try {
const result = await authService.signIn({ password: 'ok', user: 'bruno' });
expect(result).toEqual({
accessToken: 'abcdef',
});
done();
} catch (err) {
fail(err);
done();
}
});
});