2017-01-21 4 views
1

Я пытаюсь реализовать odata standard, который использует ETag. Я сложена с запросами PATCH. С каждым запросом PATCH я должен отправить etag в заголовок If-None-Match. Затем в ответ HTTP-статус 200 означает, что было применено изменение, а статус 412 означает, что базовые данные были изменены, и я должен снова его получить и как-то слить данные с сервера и текущего из приложения. Слияние не подходит для этого вопроса.Реализация ETag в Angular2

До сих пор у меня есть решение более или менее работает (добавление данных и 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: как tranform этот код Rx-только, без необходимо определить stream$?

Вопрос 2: Я хотел бы сделать ошибку вместо статуса 412. С этой ошибкой я должен каким-то образом вернуть новый объект, извлеченный с сервера. Является ли это возможным?

ответ

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!") 
    );