我有一个角度应用程序,它向Http服务发出请求,并在另一个Http服务上调用switchMap。由于某种原因,switchMap中的请求仅在第一次调用父调用时运行。否则父请求将触发,而switchMap不会触发,这里是代码:
this._receivableService.newTenantDebitCredit(tenantCredit)
.take(1)
.switchMap(result =>
// Refresh the lease receivables before giving result
this._receivableService.getAll({
refresh: true,
where: { leaseId: this.leaseId }
}).take(1).map(() => result)
)
.subscribe(
...
)
每次在上面调用newTenantDebitCredit方法时,如何在switch map中运行getAll请求?
编辑:以下是click
上调用的全部函数。当我第一次单击按钮时,给定单元执行两种方法。如果我尝试已经调用该方法的单元(没有刷新),则只执行第一个方法。我意识到很多这可能不太清楚,这是一个相当大的项目。
public submitTenantCredit() {
this.isLoading = true;
let tenantCredit: NewTenantDebitCreditData;
let receivableDefinitions: ReceivableDefinition[] = [];
// construct receivable defintions for NewTenantDebitData model
receivableDefinitions = this._constructReceivableDefinitions();
// construct data we will be POSTing to server.
tenantCredit = new NewTenantDebitCreditData({
siteId: this._apiConfig.siteId,
leaseId: this.leaseId,
isCredit: true,
receivables: receivableDefinitions,
reason: this.actionReason
});
// make service call and handle response
this._receivableService.newTenantDebitCredit(tenantCredit)
.take(1)
.switchMap(result =>
// Refresh the lease receivables before giving result
this._receivableService.getAll({
refresh: true,
where: { leaseId: this.leaseId }
}).take(1).map(() => result)
)
.take(1)
.subscribe(
(receivables) => {
this.closeReasonModal();
let refreshLeaseId = this.leaseId;
this.leaseId = refreshLeaseId;
this.isLoading = false;
this.refreshBool = !this.refreshBool;
this._debitCreditService.refreshUnitInfo();
this._notifications.success(`The tenant credit for ${this.customerName} - Unit ${this.unitNumber} was submitted successfully`);
},
(error) => {
console.error(error);
this.isLoading = false;
}
)
}
如果有帮助newTenantDebitCredit(
)是HTTP POST
请求,getAll()
是GET
请求。
答案 0 :(得分:3)
您使用了take运算符。当你的服务可观察性将发出时,take运算符将首先执行并且take将仅链接从observable发出。您的代码不会进行后续发射。 如果你想从observable中获取所有的emits,那么从你的代码中删除take。
希望它会有所帮助。
答案 1 :(得分:3)
单独测试Rx代码,这是一个模型。控制台日志每次都会发生,所以我认为您正在使用的Rx是正常的。
对可能的罪魁祸首的最佳猜测是this.refreshBool = !this.refreshBool
,但我们需要看到newTenantDebitCredit
和getAll
的内部是明确的。
// Some mocking
const _receivableService = {
newTenantDebitCredit: (tc) => {
console.log('inside newTenantDebitCredit')
return Rx.Observable.of({prop1:'someValue'})
},
getAll: (options) => {
console.log('inside getAll')
return Rx.Observable.of({prop2:'anotherValue'})
}
}
const tenantCredit = {}
// Test
_receivableService.newTenantDebitCredit(tenantCredit)
.take(1)
.switchMap(result => {
console.log('result', result)
return _receivableService.getAll({
refresh: true,
where: { leaseId: this.leaseId }
})
.take(1)
.map(() => result)
})
.take(1)
.subscribe(
(receivables) => {
console.log('receivables', receivables)
//this.refreshBool = !this.refreshBool;
},
(error) => {
console.error(error);
}
)

<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.6/Rx.js"></script>
&#13;
答案 2 :(得分:2)
首先,这与switchMap
运算符无关。
正常删除take(1)
会导致此行为。在这种情况下它不会,因为它不是一个所谓的热观察。
问题是您使用的是http.post
。这是一个冷可观察,这意味着它只返回一次值。这也是您不需要取消订阅的原因。它永远不会发射两次。可能的解决办法可能是:
答案 3 :(得分:1)
您提出问题的方式
每次在上面调用newTenantDebitCredit方法时,如何在switch map中运行getAll请求?
实际上对我来说听起来好像是从代码中的某个地方只调用 newTenantDebitCredit
,期望第二个请求发生;所以我认为这可能是对可观察链如何运作的误解。让我们举个例子:
const source$ = Observable.of(42);
source$
.map(value => 2 * value)
.subscribe(console.log);
source$
.subscribe(console.log);
您希望这会记录什么?如果你的回答是“它会记录84次”,那就错了:它记录了84和42。
从概念上讲,你的情况是一样的。第二个请求仅在newTenantDebitCredit()
返回的observable发出时发生;一些呼叫者呼叫newTenantDebitCredit
时不会发生这种情况。这是因为可观察链不会使就地观察变异,它们只会返回 new observable。
如果您希望第二个请求发生,您必须实际更改newTenantDebitCredit
方法的定义以返回可观察设置以执行第二个请求;或者,设置一个您订阅的链式observable,而不是调用newTenantDebitCredit
。
答案 4 :(得分:0)
不是答案,但我确实解决了我的问题。它几乎肯定对任何人都没用。但是它是可接收服务中的一个问题,它没有正确地监视boolean
:refresh
并且是第一次从缓存中提取值。