相依注入(Dependency Injection)
providers: [
{
provide: SomeService,
useExisting: SomeServiceV2
}
]
providers: [
{
provide: SomeService,
useClass: SomeServiceV2
}
]
providers: [
{
provide: SomeService,
useFactory: SomeServiceFactory,
deps: [HttpClient]
}
]
providers: [
{
provide: SomeService,
useValue: SomeServiceV2
}
]
沒有使用相依注入的 Service
什麼情況下會不使用 DI?
幾乎不存在這種情況,因為 DI 實在是太方便
唯一的情境就是,要使用 Service 的時間點是在 Angular 的 LifeCycle 之外,舉例來說在系統完全啟動前先備好一些設定值
來調整一下 src/app/services/config.service.ts
export class ConfigService {
private _api: string
static set(property, value) {
this['_' + property] = value;
}
static get(property) {
return this['_' + property];
}
}
接著直接在 main.ts 裡使用 ConfigService
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
import { ConfigService } from './app/services/config.service';
ConfigService.set('api', 'https://angular-in-action-portfolio.firebaseio.com/stocks.json');
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule);
HttpClient
在 StockService 裡使用 HttpClient
Fill in stock.service.ts as follows
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { ConfigService } from '../services/config.service';
import { Stock } from './stocks.model';
@Injectable()
export class StocksService {
constructor(private http: HttpClient) {}
getStocks() {
return this.http.get<Array<Stock>>(ConfigService.get('api'));
}
}
App Component 中使用 StockService
調整 app.component.ts 如下:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { AccountService } from './services/account.service';
import { StocksService } from './services/stocks.service';
import { AlertService } from './services/alert.service';
import { Stock } from './services/stocks.model';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [StocksService]
})
export class AppComponent implements OnInit, OnDestroy {
refresh: boolean = true;
stocks: Stock[] = [];
interval: any;
constructor(
private accountService: AccountService,
private stocksService: StocksService,
private alertService: AlertService ) { }
ngOnInit(): void {
this.accountService.init();
this.load();
this.interval = setInterval(() => {
if (this.refresh) {
this.load();
}
}, 15000);
}
toggleRefresh(): void {
this.refresh = !this.refresh;
let onOff = (this.refresh) ? 'on' : 'off';
this.alertService.alert(`You have turned automatic refresh ${onOff}`,'info', 0);
}
ngOnDestroy() {
clearInterval(this.interval);
}
reset(): void {
this.accountService.reset();
this.alertService.alert(`You have reset your portfolio!`);
}
private load() {
this.stocksService.getStocks().subscribe(stocks => {
this.stocks = stocks;
},
error => {
console.error(`There was an error loading stocks: ${error}`);
});
}
}
這個時候就可以把 app.component.html 所註解掉的部份全部解開,再 ng serve 看看華麗的結果了
小結:
When you subscribe to the blog, we will send you an e-mail when there are new updates on the site so you wouldn't miss them.
評論