我尝试实施使用odata standard的ETag。我已经堆积了PATCH请求。对于每个PATCH请求,我必须在标头If-None-Match
中发送etag。然后作为响应,HTTP状态200表示已应用更改,状态412表示基础数据已更改,我必须再次获取它并以某种方式合并来自服务器的数据和来自应用程序的当前数据。合并超出了这个问题的范围。
到目前为止,我已经或多或少地使用了解决方案(在缓存中添加数据和etag是get()
方法的实现):
export const HEADER_ETAG_MATCH = 'If-None-Match';
export const ODATA_ETAG_PROPERTY = '@odata.etag';
export interface CacheRecordStructure {
etag: string;
response: Response;
}
export class CachingService {
cache: { [key: string]: CacheRecordStructure } = {};
constructor(private http: Http) { }
patch(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
let stream$ = new Subject<Response>();
this.http[type](url, body, this.addEtagHeader(url, options)).subscribe(response => {
if (response.status === 412) {
delete this.cache[url];
this.get(url, options).subscribe(response2 => {
response2.status = 412;
stream$.next(response2);
});
} else {
this.cache[url].etag = response.json()[ODATA_ETAG_PROPERTY];
this.cache[url].response = response;
stream$.next(response);
}
});
return stream$.asObservable();
}
}
问题1:如何将此代码转换为仅限Rx,而无需定义stream$
?
问题2:我想抛出错误而不是状态412.有了这个错误,我应该以某种方式返回从服务器获取的新对象。有可能吗?
答案 0 :(得分:2)
微创解决方案可以使用switchMap
,它可能如下所示:
export const HEADER_ETAG_MATCH = 'If-None-Match';
export const ODATA_ETAG_PROPERTY = '@odata.etag';
export interface CacheRecordStructure {
etag: string;
response: Response;
}
export class CachingService {
cache: { [key: string]: CacheRecordStructure } = {};
constructor(private http: Http) { }
patch(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
return this.http[type](url, body, this.addEtagHeader(url, options))
.switchMap(response => {
if (response.status === 412) {
delete this.cache[url];
return this.get(url, options)
.switchMap(response2 => {
response2.status = 412;
return Observable.throw(response2);
});
} else {
this.cache[url].etag = response.json()[ODATA_ETAG_PROPERTY];
this.cache[url].response = response;
return Observable.of(response);
}
});
}
}
然后你就像使用它一样:
myCachingService.patch("myurl...", someBody)
.subscribe(
response => console.log(response),
errorWithNewObj => console.error(errorWithNewObj),
() => console.info("Done!")
);