使用 typescript,啥是最好的 Observable 类型来最好地表示没有内容的 HTTP 响应?

Posted

技术标签:

【中文标题】使用 typescript,啥是最好的 Observable 类型来最好地表示没有内容的 HTTP 响应?【英文标题】:Using typescript, what is a good Observable type to best represent a HTTP response with no content?使用 typescript,什么是最好的 Observable 类型来最好地表示没有内容的 HTTP 响应? 【发布时间】:2019-03-22 00:40:08 【问题描述】:

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

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

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

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

更好的解决方案是返回 Observable&lt;null&gt;,但我发现语义不明确,因为 null 也可能指的是 null 数据(例如,没有电话号码的客户会将 phoneNumber 属性设置为 null)。

【问题讨论】:

看看这个:***.com/questions/38548407/… 【参考方案1】:

您可以创建一个以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 like:

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

【讨论】:

【参考方案2】:

您要查找的内容确实存在,其正确类型是Observable&lt;void&gt;。就像你说的 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(...)

顺便说一句,您还可以使用 ignoreElements() 运算符将任何 Observable 转换为 Observable&lt;void&gt;

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

【讨论】:

Observable&lt;void&gt; 在技术上是有效的,但它的语义很难推理:它会发出什么东西吗?在什么意义上是“无效”的价值? empty() 很好,但就像我对@Sunil Singh 说的那样,订阅方法的使用会根据是否有内容而改变(有时使用next,有时使用complete),这太糟糕了。 好吧,它必须改变。您如何区分有效值和您不想发出任何东西的情况?这就是completeerror 通知的用途。当然,您可以使用null,但您似乎想避免这种情况。 void 类型是 TypeScript 类型,不代表任何内容(如数据库中的 NULL)。那么Observable&lt;T&gt; 是一个Observable,它发出next 类型为T 的项目。所以Observable&lt;void&gt; 是一个什么都不发射的 Observable。【参考方案3】:

您可以使用Observable.empty()

empty() 如果你已经从rxjs 导入

【讨论】:

它并不完美,因为它需要更改订阅方法(使用complete 回调而不是next)。但我同意empty 是传达具有 内容的已完成 HTTP 请求含义的最佳运算符。 @Clément 你可以使用subscribe( complete: () =&gt; ... )

以上是关于使用 typescript,啥是最好的 Observable 类型来最好地表示没有内容的 HTTP 响应?的主要内容,如果未能解决你的问题,请参考以下文章

带有 Typescript 和 ThemeProvider 的样式化组件。啥是正确的类型?

在 Typescript 中,啥是 ! (感叹号/爆炸)操作员取消引用成员时?

在 Typescript 中,啥是 ! (感叹号/爆炸)操作员取消引用成员时?

在 Typescript 中,啥是 ! (感叹号/爆炸)操作员取消引用成员时?

Python 中的“公共”或“私有”属性?啥是最好的方法?

导入和导出 Excel - 啥是最好的库? [关闭]