Rxjs takeWhile完成后的链式可观察对象未被调用?
我有以下方法,应该这样调用:Rxjs takeWhile完成后的链式可观察对象未被调用?,rxjs,observable,Rxjs,Observable,我有以下方法,应该这样调用: registerDomain(domain) { return this._adminService.registerDomain(domain) .concatMap(operation => this.getOperationDetail(operation.OperationId)) .concatMap((op) => this.createRecordSets(op)); 应调用注册域,并应返回操作ID
registerDomain(domain) {
return this._adminService.registerDomain(domain)
.concatMap(operation => this.getOperationDetail(operation.OperationId))
.concatMap((op) => this.createRecordSets(op));
10
秒之后,应调用getOperationDetail
传递operationId
10
秒调用一次getOperationDetail
,直到返回successful
getOperationDetail
完成,就应该调用createRecordSets
getChangeStatus
,直到它返回INSYNC
registerDomain(domain) {
return this._adminService.registerDomain(domain)
.concatMap(operation => this.getOperationDetail(operation.OperationId))
.concatMap(() => this._adminService.createRecordSets(domain));
}
getOperationDetail(operationId) {
return Observable.interval(10000)
.mergeMap(() => this._adminService.getOperationDetail(operationId))
.takeWhile((info) => info.Status.Value !== 'SUCCESSFUL');
}
createRecordSets(caseWebsiteUrl) {
return this._adminService.createRecordSets(caseWebsiteUrl.Url)
.concatMap(registerId => this.getChangeStatus(registerId));
}
getChangeStatus(registerId) {
return Observable.interval(5000)
.mergeMap(() => this._adminService.getChange(registerId))
.takeWhile((info) => info.ChangeInfo.Status.Value !== 'INSYNC');
}
我更新了getOperationDetail
以使用first
运算符:
getOperationDetail(operationId) {
return Observable.interval(3000)
.mergeMap(() => this._adminService.getOperationDetail(operationId))
.first((info) => info.Status.Value === 'SUCCESSFUL')
}
现在它实际上调用了createRecordSets
,但是在createRecordSets
之后,它继续调用getOperationDetail
大约13次,并最终调用getChangeStatus
。从我的角度来看,我认为它会:
getOperationDetail
,直到它收到SUCCESS
createRecordset
一次getChangeStatus
,直到它收到INSYNC
registerDomain(domain) {
return this._adminService.registerDomain(domain)
.concatMap(operation => this.getOperationDetail(operation.OperationId))
.concatMap((op) => this.createRecordSets(op));
在我将
.concatMap((op)=>this.createRecordSets(op))
链接到this.getOperationDetail
之后之前。一旦我把它移到外面,它就开始正常工作了。但我不确定为什么。有人能解释一下吗?当takeWhile
满足一个满足特定标准的值时,它完成了可观察的,而不传播该值。这意味着下一个链式运算符将不会接收该值,也不会调用其回调
假设在您的示例中,对this.\u adminService.getOperationDetail(…)的前两个调用导致非成功状态,第三个调用成功。这意味着getOperationDetail()
返回的可观察值将只产生两个info
值,每个值都具有非成功状态。同样重要的是,下一个链式concatMap
操作符将根据每个不成功的值调用其回调,这意味着createRecordset()
将被调用两次。我想你可能想避免这样
我建议使用第一个
操作符:
getOperationDetail(operationId) {
return Observable.interval(10000)
.concatMap(() => this._adminService.getOperationDetail(operationId))
.first(info => info.Status.Value !== 'SUCCESSFUL');
}
这样getOperationDetail()
将在This.\u adminService.getOperationDetail(operationId)
成功时只生成一个“成功”值。操作符发出与指定条件匹配的源可观测值的第一个值,然后完成
当涉及到错误处理时,或运算符可能很有用
更新:
您所面临的意外行为(getOperationDetail()
在first()
完成后继续被调用)似乎是在rxjs
中出现的。如中所述
每个take-ish操作符(完成时间早于其源可观测值的操作符)在与延长订阅时间的操作符(此处为switchMap)组合时,将继续订阅源可观测值
first
和takeWhile
都是此类take-ish操作符的示例,而“延长”订阅的操作符是,例如,switchMap
、concatMap
和mergeMap
。在以下示例中,当concatMap
的内部可观测值发出值时,将记录数字:
var takeish$ = Rx.Observable.interval(200)
// will keep logging until inner observable of `concatMap` is completed
.do(x => console.log(x))
.takeWhile(x => x < 2);
var source = takeish$
.concatMap(x => Rx.Observable.interval(200).take(10))
.subscribe();
您好,我先尝试了一下,效果不错,但我遇到了一个问题。我用它更新了我的帖子。我想我成功地重现了你描述的意外行为,我会很快更新答案。简而言之,first()
即使在满足指定的条件后,似乎也不会从可观察的源中取消订阅,有关详细信息,请参阅。@xaisoft,我用错误描述和可能的解决方法更新了答案。坦白地说,这个错误让我大吃一惊:)嗨,谢尔盖,我很感谢你的回答。我还发布了一个带有简单示例的问题,得到了以下回复。看起来已经修好了@xaisoft,你发布的另一个问题是绝对正确的,但它与你描述的bug无关。我相当肯定,该缺陷仍然存在于rxjs的当前版本(目前为5.4.2)中,它与first
操作符是否与concatMap
操作符链接有关。我更新了我的答案,提供了更多细节和几个可运行的代码片段来说明这个问题。