Angular 2
Dienste und Abhängigkeitsinjektion
Suche…
Beispieldienst
services / mein.service.ts
import { Injectable } from '@angular/core'; @Injectable() export class MyService { data: any = [1, 2, 3]; getData() { return this.data; } }
Die Registrierung des Service Providers in der Bootstrap-Methode macht den Service global verfügbar.
main.ts
import { bootstrap } from '@angular/platform-browser-dynamic'; import { AppComponent } from 'app.component.ts'; import { MyService } from 'services/my.service'; bootstrap(AppComponent, [MyService]);
In der Version RC5 kann der globale Service Provider in der Moduldatei registriert werden. Um eine einzige Instanz Ihres Dienstes für Ihre gesamte Anwendung zu erhalten, muss der Dienst in der Liste der Anbieter im ngmodule Ihrer Anwendung angegeben werden. 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 {}
Verwendung in MyComponent
components / my.component.ts
Alternativer Ansatz zum Registrieren von Anwendungsanbietern in Anwendungskomponenten. Wenn wir bei der Wiedergabe der Komponente Anbieter auf Komponentenebene hinzufügen, wird eine neue Instanz des Diensts erstellt.
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(); } }
Beispiel mit Promise.resolve
services / mein.service.ts
import { Injectable } from '@angular/core';
@Injectable()
export class MyService {
data: any = [1, 2, 3];
getData() {
return Promise.resolve(this.data);
}
}
getData()
jetzt wie ein REST-Aufruf, der ein Promise erstellt, das sofort aufgelöst wird. Die Ergebnisse können in .then()
und Fehler erkannt werden. Dies ist eine gute Praxis und Konvention für asynchrone Methoden.
components / 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);
}
}
Testen eines Dienstes
Bei einem Dienst, mit dem sich ein Benutzer anmelden kann:
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();
}
}
Es kann so getestet werden:
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();
}
});
});