Angular :在返回值之前等待 Observable 完成
Angular : Wait for an Observable to finish before returning the value
我有一个方法需要 return Observable。然后将该可观察值作为输入提供给第三方组件。我们无法修改第三方组件。
我在 return 获取所需的可观察对象时面临的问题是我需要对结果执行一些计算,并且此计算依赖于另一个服务调用 (_transService.getTransactions)只能在第一次服务调用后执行。
如何在 return 将其作为可观察的 (Observable < searchResult > ) 之前修改第一个服务调用的结果。
目前在下面的代码中,它无法等待调用完成和 return 空数据。
public search(): Observable<Response<ListDetail>> {
let searchResult: Response<ListDetail>;
let gridData: ListDetail[] = [];
this.post(`search`)
.pipe(
filter((response: Response<ListDetail>): boolean => response && response.status === 'Success'),
mergeMap(
(res: Response<ListDetail>): Observable<Response<Transactions[]>> => {
searchResult = res;
gridData = res.content.items;
const ids = res.content.items.map((result: ListDetail) => result.id);
return this._transService.getTransactions(ids);
}
)
)
.subscribe((res: Response<Transactions[]>) => {
const transactionsList = res.content;
gridData.forEach((item: ListDetail) => {
item.transactions = [];
transactionsList.forEach((result: Transactions) => {
const transactions = result?.transactions;
transactions.forEach((transaction: Transaction) => {
if (transaction.parentId === 0) {
item.transactions.push(transaction);
if (transaction.transactionType === 'CASH') {
if (!item.cashAmount) {
item.cashAmount = 0;
}
item.cashAmount+= transaction.amount;
} }
});
});
});
});
return of(searchResult);
}
试试这个。
public search(): Observable<Response<ListDetail>> {
let searchResult: Response<ListDetail>;
return new Observable<Response<ListDetail>>(observer => {
let gridData: ListDetail[] = [];
this.post(`search`)
.pipe(
filter((response: Response<ListDetail>): boolean => response && response.status === 'Success'),
mergeMap(
(res: Response<ListDetail>): Observable<Response<Transactions[]>> => {
searchResult = res;
gridData = res.content.items;
const ids = res.content.items.map((result: ListDetail) => result.id);
return this._transService.getTransactions(ids);
}
)
)
.subscribe((res: Response<Transactions[]>) => {
const transactionsList = res.content;
gridData.forEach((item: ListDetail) => {
item.transactions = [];
transactionsList.forEach((result: Transactions) => {
const transactions = result?.transactions;
transactions.forEach((transaction: Transaction) => {
if (transaction.parentId === 0) {
item.transactions.push(transaction);
if (transaction.transactionType === 'CASH') {
if (!item.cashAmount) {
item.cashAmount = 0;
}
item.cashAmount+= transaction.amount;
}
}
});
});
});
observer.next(searchResult);
observer.complete();
});
});
}
另一种选择是使用 tap:
public search(): Observable<Response<ListDetail>> {
return new Observable<Response<ListDetail>>(observer => {
let gridData: ListDetail[] = [];
this.post(`search`)
.pipe(
filter((response: Response<ListDetail>): boolean => response && response.status === 'Success'),
tap( res => {
observer.next(res);
observer.complete();
}),
mergeMap(
(res: Response<ListDetail>): Observable<Response<Transactions[]>> => {
searchResult = res;
gridData = res.content.items;
const ids = res.content.items.map((result: ListDetail) => result.id);
return this._transService.getTransactions(ids);
}
)
)
.subscribe((res: Response<Transactions[]>) => {
const transactionsList = res.content;
gridData.forEach((item: ListDetail) => {
item.transactions = [];
transactionsList.forEach((result: Transactions) => {
const transactions = result?.transactions;
transactions.forEach((transaction: Transaction) => {
if (transaction.parentId === 0) {
item.transactions.push(transaction);
if (transaction.transactionType === 'CASH') {
if (!item.cashAmount) {
item.cashAmount = 0;
}
item.cashAmount+= transaction.amount;
}
}
});
});
});
});
});
}
我有一个方法需要 return Observable。然后将该可观察值作为输入提供给第三方组件。我们无法修改第三方组件。
我在 return 获取所需的可观察对象时面临的问题是我需要对结果执行一些计算,并且此计算依赖于另一个服务调用 (_transService.getTransactions)只能在第一次服务调用后执行。
如何在 return 将其作为可观察的 (Observable < searchResult > ) 之前修改第一个服务调用的结果。
目前在下面的代码中,它无法等待调用完成和 return 空数据。
public search(): Observable<Response<ListDetail>> {
let searchResult: Response<ListDetail>;
let gridData: ListDetail[] = [];
this.post(`search`)
.pipe(
filter((response: Response<ListDetail>): boolean => response && response.status === 'Success'),
mergeMap(
(res: Response<ListDetail>): Observable<Response<Transactions[]>> => {
searchResult = res;
gridData = res.content.items;
const ids = res.content.items.map((result: ListDetail) => result.id);
return this._transService.getTransactions(ids);
}
)
)
.subscribe((res: Response<Transactions[]>) => {
const transactionsList = res.content;
gridData.forEach((item: ListDetail) => {
item.transactions = [];
transactionsList.forEach((result: Transactions) => {
const transactions = result?.transactions;
transactions.forEach((transaction: Transaction) => {
if (transaction.parentId === 0) {
item.transactions.push(transaction);
if (transaction.transactionType === 'CASH') {
if (!item.cashAmount) {
item.cashAmount = 0;
}
item.cashAmount+= transaction.amount;
} }
});
});
});
});
return of(searchResult);
}
试试这个。
public search(): Observable<Response<ListDetail>> {
let searchResult: Response<ListDetail>;
return new Observable<Response<ListDetail>>(observer => {
let gridData: ListDetail[] = [];
this.post(`search`)
.pipe(
filter((response: Response<ListDetail>): boolean => response && response.status === 'Success'),
mergeMap(
(res: Response<ListDetail>): Observable<Response<Transactions[]>> => {
searchResult = res;
gridData = res.content.items;
const ids = res.content.items.map((result: ListDetail) => result.id);
return this._transService.getTransactions(ids);
}
)
)
.subscribe((res: Response<Transactions[]>) => {
const transactionsList = res.content;
gridData.forEach((item: ListDetail) => {
item.transactions = [];
transactionsList.forEach((result: Transactions) => {
const transactions = result?.transactions;
transactions.forEach((transaction: Transaction) => {
if (transaction.parentId === 0) {
item.transactions.push(transaction);
if (transaction.transactionType === 'CASH') {
if (!item.cashAmount) {
item.cashAmount = 0;
}
item.cashAmount+= transaction.amount;
}
}
});
});
});
observer.next(searchResult);
observer.complete();
});
});
}
另一种选择是使用 tap:
public search(): Observable<Response<ListDetail>> {
return new Observable<Response<ListDetail>>(observer => {
let gridData: ListDetail[] = [];
this.post(`search`)
.pipe(
filter((response: Response<ListDetail>): boolean => response && response.status === 'Success'),
tap( res => {
observer.next(res);
observer.complete();
}),
mergeMap(
(res: Response<ListDetail>): Observable<Response<Transactions[]>> => {
searchResult = res;
gridData = res.content.items;
const ids = res.content.items.map((result: ListDetail) => result.id);
return this._transService.getTransactions(ids);
}
)
)
.subscribe((res: Response<Transactions[]>) => {
const transactionsList = res.content;
gridData.forEach((item: ListDetail) => {
item.transactions = [];
transactionsList.forEach((result: Transactions) => {
const transactions = result?.transactions;
transactions.forEach((transaction: Transaction) => {
if (transaction.parentId === 0) {
item.transactions.push(transaction);
if (transaction.transactionType === 'CASH') {
if (!item.cashAmount) {
item.cashAmount = 0;
}
item.cashAmount+= transaction.amount;
}
}
});
});
});
});
});
}