如何删除 Observable 的响应
How to drop the response of an Observable
在 的帮助下,我正在以定义的时间模式向我的服务器发出连续请求。在我处理完响应的内容后,可能会在特殊条件下 取决于之前的响应 我需要删除响应,因此不会将其传递给服务的订阅者:
@Injectable()
export class LoggerService {
constructor(private http: Http) { }
private apiURL = 'assets/file.json';
getList() {
return Observable.timer(0, 1000)
.concatMap(() => this.http.get(this.apiURL))
.map(this.extractData)
.catch(this.handleError););
}
private extractData(res: Response) {
var fooot = new Foo();
fooot.fillFromJSON(JSON.stringify(res.json()));
if(fooot.getProperty()){
//DROP IT
}
return fooot;
}
private handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg);
return Observable.throw(errMsg);
}
}
然后从组件的 ngOnInit
调用 getList()
方法。
目前我能想到两种可能的解决方案,购买也许有一种 better/clearer 方法可以解决这个问题:
如果我必须删除响应,我会创建一个特殊对象,该对象可被 getList()
的订阅者识别,然后进行专门处理。但是这个解决方案会非常丑陋,因为丢弃的响应离开了我的服务,我需要在服务之外额外编写代码来处理这种情况。
当我必须放弃响应时抛出异常。然后异常被捕获、识别(以区别于其他情况)然后在没有任何 notice/output 的情况下被丢弃。之后,可观察对象重新启动。这种方法的优点是应该丢弃的可观察对象不会离开服务,但我不喜欢在这种情况下对控制流使用异常。
我尝试了两种解决方案并且它们都有效,但我希望有一些更好的方法。
如果我没理解错的话,您正在寻找 switchMap
运算符。
如果在 1 秒(指定时间间隔)内没有响应到达,HTTP 请求将被静默取消,并启动另一个请求。
更新:
如果您希望手动取消 HTTP 请求,则必须创建 cancelSubject: Subject
并在 HTTP 请求上定义 takeUntil(cancelSubject)
。
要取消 HTTP 请求,只需调用 cancelSubject.next(true)
,这将取消 HTTP 请求,因为 takeUntil
生效。
请记住,一秒钟后,请求将重新启动。如果你想取消计时器,你将不得不把 .takeUntil(cancelSubject)
放在外部 observable 上。
我最终使用 distinctUntilChanged
来实现我的目标:
getList() {
return Observable.timer(0, 1000)
.concatMap(() => this.http.get(this.apiURL)
.distinctUntilChanged(null, x => x.json().info[1].value)
.map(this.extractData)
.catch(this.handleError);
}
因此,如果当前和最后一个响应共享相同的特定值,则最新的响应将被丢弃。我想我的问题不够清楚,我没有提到放弃回复的决定取决于前一个。
这种方法的缺点 是响应必须被解析两次,但我想这是不可避免的。很高兴知道 json 方法是否比结果(正文)的完整字符串比较更快。
如果删除响应的决定仅取决于当前响应,我建议使用 filter。
在
@Injectable()
export class LoggerService {
constructor(private http: Http) { }
private apiURL = 'assets/file.json';
getList() {
return Observable.timer(0, 1000)
.concatMap(() => this.http.get(this.apiURL))
.map(this.extractData)
.catch(this.handleError););
}
private extractData(res: Response) {
var fooot = new Foo();
fooot.fillFromJSON(JSON.stringify(res.json()));
if(fooot.getProperty()){
//DROP IT
}
return fooot;
}
private handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg);
return Observable.throw(errMsg);
}
}
然后从组件的 ngOnInit
调用 getList()
方法。
目前我能想到两种可能的解决方案,购买也许有一种 better/clearer 方法可以解决这个问题:
如果我必须删除响应,我会创建一个特殊对象,该对象可被
getList()
的订阅者识别,然后进行专门处理。但是这个解决方案会非常丑陋,因为丢弃的响应离开了我的服务,我需要在服务之外额外编写代码来处理这种情况。当我必须放弃响应时抛出异常。然后异常被捕获、识别(以区别于其他情况)然后在没有任何 notice/output 的情况下被丢弃。之后,可观察对象重新启动。这种方法的优点是应该丢弃的可观察对象不会离开服务,但我不喜欢在这种情况下对控制流使用异常。
我尝试了两种解决方案并且它们都有效,但我希望有一些更好的方法。
如果我没理解错的话,您正在寻找 switchMap
运算符。
如果在 1 秒(指定时间间隔)内没有响应到达,HTTP 请求将被静默取消,并启动另一个请求。
更新:
如果您希望手动取消 HTTP 请求,则必须创建 cancelSubject: Subject
并在 HTTP 请求上定义 takeUntil(cancelSubject)
。
要取消 HTTP 请求,只需调用 cancelSubject.next(true)
,这将取消 HTTP 请求,因为 takeUntil
生效。
请记住,一秒钟后,请求将重新启动。如果你想取消计时器,你将不得不把 .takeUntil(cancelSubject)
放在外部 observable 上。
我最终使用 distinctUntilChanged
来实现我的目标:
getList() {
return Observable.timer(0, 1000)
.concatMap(() => this.http.get(this.apiURL)
.distinctUntilChanged(null, x => x.json().info[1].value)
.map(this.extractData)
.catch(this.handleError);
}
因此,如果当前和最后一个响应共享相同的特定值,则最新的响应将被丢弃。我想我的问题不够清楚,我没有提到放弃回复的决定取决于前一个。
这种方法的缺点 是响应必须被解析两次,但我想这是不可避免的。很高兴知道 json 方法是否比结果(正文)的完整字符串比较更快。
如果删除响应的决定仅取决于当前响应,我建议使用 filter。