以下组件使用服务通过HttpClient模块从服务器获取数据。服务基本上有效。选择单个bankaccount时,将销毁BankaccountListComponent并显示BankaccountEditComponent。单击保存时,执行BankaccountEditComponent中的方法saveBankaccount(参见下文)。数据被发送到服务器并存储(始终)。保存数据后,将显示BankaccountListComponent。在ngOnInit中,它应该再次获取数据。
问题是执行BankaccountListComponent的ngOnInit(总是),但不会始终获取数据。它不会一直有效,我无法弄清楚原因。
来自BankaccountEditComponent:
saveBankaccount() {
this.subscription = this.route.params
.subscribe(params => {
const id = (params['id'] || '');
if (id) {
this.bankaccountService.update(id, this.bankaccount).subscribe(bankaccount => {
this.bankaccount = bankaccount;
});
} else {
this.bankaccountService.add(this.bankaccount).subscribe(bankaccount => {
this.bankaccount = bankaccount;
});
}
const relUrl = this.router.url.includes('edit') ? '../..' : '..';
this.router.navigate([relUrl], { relativeTo: this.route });
});
}
所有BankaccountListComponent:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { BankaccountService } from '../../services/bankaccount.service';
import { Bankaccount } from '../../domain/bankaccount';
@Component({
selector: 'ac-bankaccount-list',
templateUrl: './bankaccount-list.component.html',
styleUrls: ['./bankaccount-list.component.css']
})
export class BankaccountListComponent implements OnInit, OnDestroy {
bankaccounts: Bankaccount[];
bankaccountSelectedId: number;
constructor(private bankaccountService: BankaccountService) { }
ngOnInit() {
console.log('init BankaccountListComponent');
this.getBankaccounts();
}
ngOnDestroy() {
console.log('destroying BankaccountListComponent');
}
getBankaccounts() {
this.bankaccountService.getBankaccounts().subscribe(bankaccounts => {
this.bankaccounts = bankaccounts;
console.log('this.bankaccount: ' + Array.prototype.map.call(this.bankaccounts, function(bankaccount) { return bankaccount.name; }).join(", "));
});
}
selectBankaccount(bankaccountId: number) {
this.bankaccountSelectedId = bankaccountId;
console.log('id of bankaccount selected: ' + this.bankaccountSelectedId);
}
deleteBankaccount(bankaccountId: number) {
console.log('id of bankaccount to delete: ' + bankaccountId);
this.bankaccountService.delete(bankaccountId).subscribe(_ => {
this.getBankaccounts();
});
}
}
所有BankaccountService:
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import 'rxjs/add/operator/map';
import { Bankaccount } from '../domain/bankaccount';
@Injectable()
export class BankaccountService {
private headers = new HttpHeaders();
private bankaccountsUrl = 'http://localhost:8090/account/accounts/';
constructor(private httpClient: HttpClient) {
this.headers = this.headers.set('Content-Type', 'application/json');
this.headers = this.headers.set('Accept', 'application/json');
}
getBankaccounts(): Observable<Bankaccount[]> {
return this.httpClient.get<Bankaccount[]>(this.bankaccountsUrl).map((result: any) => {
console.log('fetched ' + result._embedded.accounts.length + ' bankaccounts from server');
return result._embedded.accounts;
});
}
getBankaccount(id: number): Observable<Bankaccount> {
return this.httpClient.get<Bankaccount>(this.bankaccountsUrl + id).map((result: any) => {
console.log('fetched bankaccount with id ' + result.id + ' from server');
return result;
});
}
update(id: number, bankaccount: any): Observable<Bankaccount> {
return this.httpClient.put<Bankaccount>(this.bankaccountsUrl + id, bankaccount);
}
add(bankaccount: Bankaccount): Observable<Bankaccount> {
return this.httpClient.post<Bankaccount>(this.bankaccountsUrl, bankaccount);
}
delete(id: number): Observable<Bankaccount> {
console.log('will delete bankaccount ' + this.bankaccountsUrl + id);
return this.httpClient.delete<Bankaccount>(this.bankaccountsUrl + id);
}
}
答案 0 :(得分:1)
(评论后重写)
首先,嵌套订阅是不好的做法。
除其他原因外,由于可读性。很难判断哪些动作将以哪种顺序执行。
首先修复:使用flatMap
运算符链接Observable
s。
this.subscription = this.route.params
.flatMap(params => { // use 'flatMap' instead of 'subscribe' here
const id = (params['id'] || '');
if (id) {
// here return the Observable that goes next instead of subscribing
return this.bankaccountService.update(id, this.bankaccount);
} else {
// here also
return this.bankaccountService.add(this.bankaccount);
}
})
// here you action following the 'update' or 'add'
// (what you wanted to do nested in the previous block)
.subscribe(bankaccount => {
this.bankaccount = bankaccount;
});
const relUrl = this.router.url.includes('edit') ? '../..' : '..';
this.router.navigate([relUrl], { relativeTo: this.route });
});
根据您上次的评论,这是您的问题的实际原因:您有异步操作订单问题。
您希望在创建/编辑操作返回后仅导航。目前,编辑和获取之间存在竞争条件。
你在选择之前调用更新/创建(这是有意义的),但由于它们是异步的,有时候select操作会在执行更新/创建之前返回,因此症状是你见证。 (有时接收旧版本,即使始终执行更新)
解决方案:仅在“编辑/创建”完成后调用“阅读”操作。
希望这里的修复非常简单:只需在订阅回调中移动router.navigate部分,因为该部分在操作返回后执行:
.subscribe(bankaccount => {
this.bankaccount = bankaccount;
const relUrl = this.router.url.includes('edit') ? '../..' : '..';
this.router.navigate([relUrl], { relativeTo: this.route });
});