使用打字稿,什么是最佳的可观察类型才能最好地表示没有内容的HTTP响应?

时间:2018-10-17 10:48:02

标签: angular typescript http rxjs

使用打字稿,Angular 6+和rxjs,如何最好地向调用者表示HTTP响应内容为空(Content-Length = 0)?

如果未在方法调用中指定类型(getpost等),则返回Observable<Object>,这对响应内容具有误导性,因为可能会尝试使用给定的对象

let response: Observable<Object> = httpClient.post('...');
response.subscribe(o => ...);

在这种情况下,o始终为null,但这不是显式的,也不由编译器检查。

一个更好的解决方案是返回Observable<null>,但是我发现语义是模棱两可的,因为null也可以引用null数据(例如,没有电话号码的客户会将phoneNumber属性设置为null)

3 个答案:

答案 0 :(得分:2)

您可以创建一种以Observable的形式发送请求的方法,

 // Add a new comment
    addComment (body: Object): Observable<Comment[]> {
        let bodyString = JSON.stringify(body); // Stringify payload
        let headers      = new Headers({ 'Content-Type': 'application/json' }); // ... Set content type to JSON
        let options       = new RequestOptions({ headers: headers }); // Create a request option

        return this.http.post(this.commentsUrl, body, options) // ...using post request
                         .map((res:Response) => res.json()) // ...and calling .json() on the response to return data
                         .catch((error:any) => Observable.throw(error.json().error || 'Server error')); //...errors if any
    }   

    // Update a comment
    updateComment (body: Object): Observable<Comment[]> {
        let bodyString = JSON.stringify(body); // Stringify payload
        let headers      = new Headers({ 'Content-Type': 'application/json' }); // ... Set content type to JSON
        let options       = new RequestOptions({ headers: headers }); // Create a request option

        return this.http.put(`${this.commentsUrl}/${body['id']}`, body, options) // ...using put request
                         .map((res:Response) => res.json()) // ...and calling .json() on the response to return data
                         .catch((error:any) => Observable.throw(error.json().error || 'Server error')); //...errors if any
    }   

    // Delete a comment
    removeComment (id:string): Observable<Comment[]> {
        return this.http.delete(`${this.commentsUrl}/${id}`) // ...using put request
                         .map((res:Response) => res.json()) // ...and calling .json() on the response to return data
                         .catch((error:any) => Observable.throw(error.json().error || 'Server error')); //...errors if any
    }

或者像下面这样简单地使用HttpClient

getConfigResponse(): Observable<HttpResponse<Config>> {
  return this.http.get<Config>(
    this.configUrl, { observe: 'response' });
}

    addHero (hero: Hero): Observable<Hero> {
  return this.http.post<Hero>(this.heroesUrl, hero, httpOptions)
    .pipe(
           catchError(this.handleError('addHero', hero))
         );
    }

答案 1 :(得分:1)

您可以使用Observable.empty()

empty()(如果您是从rxjs导入的)

答案 2 :(得分:1)

您要查找的内容确实存在,并且其正确类型为Observable<void>。就像您说的那样,null是可由任何Observable生成的常规值。在RxJS 6中,它由empty()表示,它与其他任何Observable一样,但是不发出任何next值,而只是发送complete信号。

import { empty, EMPTY } from 'rxjs';

empty().subscribe(...) // will receive just the `complete` notification

// or you can use EMPTY

EMPTY.subscribe(...)

通过这种方式,您还可以使用Observable<void>运算符将任何Observable转换为ignoreElements()

还有never()NEVER可观察对象,但不要将它们误认为empty(),因为它们不会发出任何东西(甚至不发出complete通知)。