使用 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)?
如果没有在方法调用中指定类型(get
、post
等),则返回一个Observable<Object>
,这对响应内容具有误导性,因为可能会试图使用给定的对象:
let response: Observable<Object> = httpClient.post('...');
response.subscribe(o => ...);
在这种情况下,o
始终为 null,但这不是显式的,也不是由编译器检查的。
更好的解决方案是返回 Observable<null>
,但我发现语义不明确,因为 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<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(...)
顺便说一句,您还可以使用 ignoreElements()
运算符将任何 Observable 转换为 Observable<void>
。
还有never()
和NEVER
Observables,但不要将它们误认为empty()
,因为它们不会发出任何东西(甚至不会发出complete
通知)。
【讨论】:
Observable<void>
在技术上是有效的,但它的语义很难推理:它会发出什么东西吗?在什么意义上是“无效”的价值? empty()
很好,但就像我对@Sunil Singh 说的那样,订阅方法的使用会根据是否有内容而改变(有时使用next
,有时使用complete
),这太糟糕了。
好吧,它必须改变。您如何区分有效值和您不想发出任何东西的情况?这就是complete
和error
通知的用途。当然,您可以使用null
,但您似乎想避免这种情况。 void
类型是 TypeScript 类型,不代表任何内容(如数据库中的 NULL
)。那么Observable<T>
是一个Observable,它发出next
类型为T
的项目。所以Observable<void>
是一个什么都不发射的 Observable。【参考方案3】:
您可以使用Observable.empty()
或
empty()
如果你已经从rxjs
导入
【讨论】:
它并不完美,因为它需要更改订阅方法(使用complete
回调而不是next
)。但我同意empty
是传达具有空 内容的已完成 HTTP 请求含义的最佳运算符。
@Clément 你可以使用subscribe( complete: () => ... )
以上是关于使用 typescript,啥是最好的 Observable 类型来最好地表示没有内容的 HTTP 响应?的主要内容,如果未能解决你的问题,请参考以下文章
带有 Typescript 和 ThemeProvider 的样式化组件。啥是正确的类型?
在 Typescript 中,啥是 ! (感叹号/爆炸)操作员取消引用成员时?
在 Typescript 中,啥是 ! (感叹号/爆炸)操作员取消引用成员时?