我正在从Razor视图转移到Angular 4,并试图弄清楚如何在不依赖Ajax调用的情况下将全局常量从服务器传递到Angular。
因此服务器常量将是事务状态,例如:
Id: 1->Active
Id: 2-> Inactive
Id: 3->Cancelled etc
因此这些状态保存在数据库中,用于查询各种事务,因此在许多组件中都需要
在Razor视图中,我曾经将这些值与viewmodel
一起传递。但在Angular目前我可以看到两个选项:
ngOnInit
中进行Ajax调用选项1会大幅增加服务器调用次数 - >所以我试图避免这种情况。
选项2将要求我在我的应用程序中的多个位置更改状态,例如,如果添加新状态,我也不喜欢。
我正在寻找一种方法将所有常量发送到Angular,例如重载应用程序或重新加载页面。
答案 0 :(得分:2)
最好让服务缓存局部变量中的信息。然后,当您将服务注入到组件中,并且一个服务器调用服务函数时,该服务将检查本地变量。如果变量中存在某些内容,请使用它,如果没有,请加载数据并将其缓存以供以后使用。
由于服务是单例,因此除非您创建某种机制来使值超时,否则数据只应加载一次。因此,第一次调用服务时,将获取数据。之后,应该使用局部变量(下面称为globals
)。
服务:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable()
export class GlobalsService {
private globals: any;
constructor(private httpClient: HttpClient) { }
getGlobals(): any {
if (this.globals) {
return this.globals;
} else {
// call your API to get global data from DB
this.httpClient.get<any>('...').subscribe((data: any) => {
this.globals = data;
return this.globals;
});
}
}
}
使用该服务的组件:
import { GlobalsService } from './../globals.service';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-tester',
templateUrl: './tester.component.html',
styleUrls: ['./tester.component.css']
})
export class TesterComponent implements OnInit {
constructor(private globalsService: GlobalsService) { }
ngOnInit() {
// Do something here with the globals from the service
const gbls = this.globalsService.getGlobals();
if (gbls) {
// ... maybe put these in a variable for later use, what ever you need
}
}
}
执行此操作将使您不必执行您提到的Ajax调用,并避免必须将代码保存在多个位置。服务模式提供了一个很好的中心位置,可以在应用程序的生命周期内保留这些数据。您需要做的就是将服务注入到需要它的组件或其他服务中。
答案 1 :(得分:2)
您需要使用ReplaySubject
根据rxjs文档
ReplaySubject:表示既是可观察序列又是观察者的对象。每个通知都会广播给所有订阅的
请查看此代码段
export class GlobalConstants{
Status:number[];
}
import { Observable, ReplaySubject } from 'rxjs';
import { GlobalConstants } from '../models/GlobalConstants';
@Injectable()
export class YourService {
//This line will cache the latest list you will get from the server
private dataSubject = new ReplaySubject<GlobalConstants>();
//you will use this observer in your components to subscribe to the getStatus result
yourStatusList$: Observable<GlobalConstants> = this.dataSubject.asObservable();
constructor(private http: Http) {
this.getStatus()
}
getStatus() {
return this.http.get('url').subscribe(res => {
this.dataSubject.next(res);
})
}
export class ExampleComponent {
public statusList;
public constructor(private _yourService: YourService) {
this.getStatus();
}
getStatus(): void {
this._yourService.yourStatusList$.subscribe(
result => {
this.statusList = result;
}
)
}
}
当角度创建服务时,它将在每个应用程序生命周期中调用getStatus方法一次,然后从服务器获取状态列表,然后您将需要在组件中订阅yourStatusList $,对于每个子目录将获得最新的缓存列表,如果您的服务器中的列表发生更改,您只需要调用YourService.getStatus,然后您将再次获取状态列表,订阅此观察者的所有组件都将收到新列表的通知
让我们接受你的两个挑战
1 - 在需要这些常量的每个组件的ngOnInit中进行Ajax调用
- 使用此代码,您的应用程序将调用服务器以获取状态列表,因此您不需要在每个组件的ngOnInit中进行Ajax调用
2 - 如果添加了新状态,设置静态模型以保存这些值将要求我在应用程序的多个位置更改状态
- 如果添加了新状态,您只需要在代码中的任何位置调用YourService.getStatus一次,订阅yourStatusList的所有组件都会收到新状态列表的通知
注意:您必须不使用提供程序:组件中的[yourService]导致如果您使用它,它将创建一个新对象并且不会使用全局对象,只需在@NgModule提供程序中添加您的服务并使用用于注入服务对象的组件构造函数
答案 2 :(得分:1)
您可以在razor视图中的app元素中添加常量作为属性
<app someatt="{ your json data here }">Loading...</app>
然后在你的应用程序的根组件上访问它们:
export class AppComponent implements OnInit {
constructor(
private el: ElementRef
) {
}
ngOnInit() {
console.log(this.el.nativeElement.attributes["someatt"].value);
}
}
然后你可以拥有一个全局服务,其状态数据在ngOnInit上设置并在所有组件中使用