服务数据 getter 在 Angular 中返回未定义
Service data getter returning undefined in Angular
我无法找出为什么在管道访问数据时我的 ShopManagerService
一直返回 undefined
。这是 ShopManagerService
:
@Injectable({ providedIn: 'root' })
export class ShopManagerService {
private shopPreferences: ShopPreferences = null;
setPreferences(shopPreferences: ShopPreferences) {
this.shopPreferences = shopPreferences;
}
getDateFormat(){
if(this.shopPreferences == null || this.shopPreferences.time_format.date == null) return;
return this.shopPreferences.time_format.date;
}
...
// more data getters
}
之前的字段shopPreferences
是在服务ApiManagerService
中设置的,像这样:
@Injectable({ providedIn: 'root' })
export class ApiManagerService {
private token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MjcwMjA3MiwidGltZXN0YW1wIjoiMjAyMS0wNC0wOSAwOToxNToxNS4';
private webzine_id: string = "2702072";
constructor(private http: HttpClient, private shopManager: ShopManagerService) {
// We want to keep shop preferences updated throughout execution
timer(0, 5000).pipe(
filter(() => this.webzine_id && this.webzine_id !== ""),
switchMap(() => this.fetchShopPreferences().pipe(first()))
)
.subscribe(preferences => this.shopManager.setPreferences(preferences));
}
fetchShopPreferences() {
const url = "https://commerce.ww-api.com/commerceapi/v1/front/front_url/" + this.webzine_id + "/";
return this.http
.get<ShopPreferences>(url, {
headers: new HttpHeaders({
token: this.token,
}),
});
}
...
// more api requests
}
组件如下所示:
@Component({
selector: 'app-order-details',
templateUrl: './order-details.component.html',
styleUrls: ['./order-details.component.css']
})
export class OrderDetailsComponent {
constructor(private apiManager: ApiManagerService, private shopPreferencesService: ShopManagerService){ }
closeDetails(){
/* implement close details functionality */
}
}
在 .html 中调用管道,如下所示:
<div id="details-container">
<div id="details-header">
<div class="header-text">
<!-- hard coded for now -->
<label>#3172</label>
<label>{{"01/18/2021" | addOrderDateHourFormat:"date"}}</label>
</div>
<div class="close-button" (click)="closeDetails()">
<img src="../../../assets/my-orders/close-icon.svg">
</div>
</div>
<app-order-properties></app-order-properties>
<app-order-channel></app-order-channel>
</div>
在管道内部,代码如下所示:
@Pipe({
name: 'addOrderDateHourFormat',
})
export class OrderDateFormatPipe implements PipeTransform {
constructor(private formatService: FormatManagerService){}
transform(value: string, type: string, trigger: number) {
if(type === "hour"){
return this.formatService.formatTime(value);
}
else if(type === "date"){
return this.formatService.formatDate(value);
}
else if(type === "date+hour"){
return this.formatService.formatDateAndTime(value)
}
}
}
最后,这是 FormatManagerService
:
里面的样子
@Injectable({ providedIn: 'root' })
export class FormatManagerService {
constructor(private datePipe: DatePipe, private shopPrefencesService: ShopManagerService) {}
formatDate(date: string){
let dateFormat = this.shopPrefencesService.getDateFormat(); // returning undefined
if(dateFormat === "GBCOMMERCE_DATEFORMAT_1"){
return this.datePipe.transform(date, 'EEEE, LLLL d yyyy');
}
else if(dateFormat === "GBCOMMERCE_DATEFORMAT_2"){
return this.datePipe.transform(date, 'LLLL d yyyy');
}
else if(dateFormat === "GBCOMMERCE_DATEFORMAT_3"){
return this.datePipe.transform(date, 'MM/d/yyyy');
}
else if(dateFormat === "GBCOMMERCE_DATEFORMAT_4"){
return this.datePipe.transform(date, 'MM.d.yyyy');
}
else if(dateFormat === "GBCOMMERCE_DATEFORMAT_5"){
return this.datePipe.transform(date, 'MM-d-yyyy');
}
}
...
// more format methods
}
为什么formatDate()
方法中的调用this.shopPrefencesService.getDateFormat()
一直返回undefined
?我在这里错过了什么?
在此先感谢您的帮助。
编辑:添加。html 和管道代码。
我会说这是因为异步。我认为您在 REST 调用 returns 值之前很久就调用了日期管道。而且管道只被发射一次。
我的建议如下。
使您的 ShopPreferences 成为 BehaviorSubject 类型的 Observable,并等待在 OrderDetailsComponent 中设置值。仅当该值存在时才渲染 div.
您的 ShopManagerService
@Injectable({ providedIn: 'root' })
export class ShopManagerService {
private shopPreferences: BehaviorSubject<ShopPreferences> = new BehaviorSubject<ShopPreferences>(null);
setPreferences(shopPreferences: ShopPreferences): void {
this.shopPreferences.next(shopPreferences);
}
getPreferencesAsObservable(): Observable<ShopPreferences> {
return this.shopPreferences.asObservable();
}
getDateFormat(): Date{
if (this.shopPreferences.getValue() === null || this.shopPreferences.getValue().time_format.date === null) {
return;
}
return this.shopPreferences.getValue().time_format.date;
}
// more data getters
}
您的 OrderDetailsComponent
@Component({
selector: 'app-order-details',
templateUrl: './order-details.component.html',
styleUrls: ['./order-details.component.css']
})
export class OrderDetailsComponent {
shopPreferencesArePresent = false;
constructor(private apiManager: ApiManagerService, private shopPreferencesService: ShopManagerService){
this.shopPreferencesService.getPreferencesAsObservable().subscribe( value => {
if (value) {
this.shopPreferencesArePresent = true;
}
});
}
closeDetails(){
/* implement close details functionality */
}
}
以及您的 OrderDetailsComponent 的 HTML
<div id="details-container">
<div id="details-header">
<div *ngIf="shopPreferencesArePresent" class="header-text">
<!-- hard coded for now -->
<label>#3172</label>
<label>{{"01/18/2021" | addOrderDateHourFormat:"date"}}</label>
</div>
<div class="close-button" (click)="closeDetails()">
<img src="../../../assets/my-orders/close-icon.svg">
</div>
</div>
<app-order-properties></app-order-properties>
<app-order-channel></app-order-channel>
</div>
我无法找出为什么在管道访问数据时我的 ShopManagerService
一直返回 undefined
。这是 ShopManagerService
:
@Injectable({ providedIn: 'root' })
export class ShopManagerService {
private shopPreferences: ShopPreferences = null;
setPreferences(shopPreferences: ShopPreferences) {
this.shopPreferences = shopPreferences;
}
getDateFormat(){
if(this.shopPreferences == null || this.shopPreferences.time_format.date == null) return;
return this.shopPreferences.time_format.date;
}
...
// more data getters
}
之前的字段shopPreferences
是在服务ApiManagerService
中设置的,像这样:
@Injectable({ providedIn: 'root' })
export class ApiManagerService {
private token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MjcwMjA3MiwidGltZXN0YW1wIjoiMjAyMS0wNC0wOSAwOToxNToxNS4';
private webzine_id: string = "2702072";
constructor(private http: HttpClient, private shopManager: ShopManagerService) {
// We want to keep shop preferences updated throughout execution
timer(0, 5000).pipe(
filter(() => this.webzine_id && this.webzine_id !== ""),
switchMap(() => this.fetchShopPreferences().pipe(first()))
)
.subscribe(preferences => this.shopManager.setPreferences(preferences));
}
fetchShopPreferences() {
const url = "https://commerce.ww-api.com/commerceapi/v1/front/front_url/" + this.webzine_id + "/";
return this.http
.get<ShopPreferences>(url, {
headers: new HttpHeaders({
token: this.token,
}),
});
}
...
// more api requests
}
组件如下所示:
@Component({
selector: 'app-order-details',
templateUrl: './order-details.component.html',
styleUrls: ['./order-details.component.css']
})
export class OrderDetailsComponent {
constructor(private apiManager: ApiManagerService, private shopPreferencesService: ShopManagerService){ }
closeDetails(){
/* implement close details functionality */
}
}
在 .html 中调用管道,如下所示:
<div id="details-container">
<div id="details-header">
<div class="header-text">
<!-- hard coded for now -->
<label>#3172</label>
<label>{{"01/18/2021" | addOrderDateHourFormat:"date"}}</label>
</div>
<div class="close-button" (click)="closeDetails()">
<img src="../../../assets/my-orders/close-icon.svg">
</div>
</div>
<app-order-properties></app-order-properties>
<app-order-channel></app-order-channel>
</div>
在管道内部,代码如下所示:
@Pipe({
name: 'addOrderDateHourFormat',
})
export class OrderDateFormatPipe implements PipeTransform {
constructor(private formatService: FormatManagerService){}
transform(value: string, type: string, trigger: number) {
if(type === "hour"){
return this.formatService.formatTime(value);
}
else if(type === "date"){
return this.formatService.formatDate(value);
}
else if(type === "date+hour"){
return this.formatService.formatDateAndTime(value)
}
}
}
最后,这是 FormatManagerService
:
@Injectable({ providedIn: 'root' })
export class FormatManagerService {
constructor(private datePipe: DatePipe, private shopPrefencesService: ShopManagerService) {}
formatDate(date: string){
let dateFormat = this.shopPrefencesService.getDateFormat(); // returning undefined
if(dateFormat === "GBCOMMERCE_DATEFORMAT_1"){
return this.datePipe.transform(date, 'EEEE, LLLL d yyyy');
}
else if(dateFormat === "GBCOMMERCE_DATEFORMAT_2"){
return this.datePipe.transform(date, 'LLLL d yyyy');
}
else if(dateFormat === "GBCOMMERCE_DATEFORMAT_3"){
return this.datePipe.transform(date, 'MM/d/yyyy');
}
else if(dateFormat === "GBCOMMERCE_DATEFORMAT_4"){
return this.datePipe.transform(date, 'MM.d.yyyy');
}
else if(dateFormat === "GBCOMMERCE_DATEFORMAT_5"){
return this.datePipe.transform(date, 'MM-d-yyyy');
}
}
...
// more format methods
}
为什么formatDate()
方法中的调用this.shopPrefencesService.getDateFormat()
一直返回undefined
?我在这里错过了什么?
在此先感谢您的帮助。
编辑:添加。html 和管道代码。
我会说这是因为异步。我认为您在 REST 调用 returns 值之前很久就调用了日期管道。而且管道只被发射一次。
我的建议如下。
使您的 ShopPreferences 成为 BehaviorSubject 类型的 Observable,并等待在 OrderDetailsComponent 中设置值。仅当该值存在时才渲染 div.
您的 ShopManagerService
@Injectable({ providedIn: 'root' })
export class ShopManagerService {
private shopPreferences: BehaviorSubject<ShopPreferences> = new BehaviorSubject<ShopPreferences>(null);
setPreferences(shopPreferences: ShopPreferences): void {
this.shopPreferences.next(shopPreferences);
}
getPreferencesAsObservable(): Observable<ShopPreferences> {
return this.shopPreferences.asObservable();
}
getDateFormat(): Date{
if (this.shopPreferences.getValue() === null || this.shopPreferences.getValue().time_format.date === null) {
return;
}
return this.shopPreferences.getValue().time_format.date;
}
// more data getters
}
您的 OrderDetailsComponent
@Component({
selector: 'app-order-details',
templateUrl: './order-details.component.html',
styleUrls: ['./order-details.component.css']
})
export class OrderDetailsComponent {
shopPreferencesArePresent = false;
constructor(private apiManager: ApiManagerService, private shopPreferencesService: ShopManagerService){
this.shopPreferencesService.getPreferencesAsObservable().subscribe( value => {
if (value) {
this.shopPreferencesArePresent = true;
}
});
}
closeDetails(){
/* implement close details functionality */
}
}
以及您的 OrderDetailsComponent 的 HTML
<div id="details-container">
<div id="details-header">
<div *ngIf="shopPreferencesArePresent" class="header-text">
<!-- hard coded for now -->
<label>#3172</label>
<label>{{"01/18/2021" | addOrderDateHourFormat:"date"}}</label>
</div>
<div class="close-button" (click)="closeDetails()">
<img src="../../../assets/my-orders/close-icon.svg">
</div>
</div>
<app-order-properties></app-order-properties>
<app-order-channel></app-order-channel>
</div>