W3Cschool
恭喜您成為首批注冊用戶
獲得88經驗值獎勵
使用 HTTPClient.get()
方法從服務器獲取數據。該異步方法會發(fā)送一個 HTTP 請求,并返回一個 Observable
,它會在收到響應時發(fā)出所請求到的數據。返回的類型取決于你調用時傳入的 observe
和 responseType
參數。
get()
方法有兩個參數。要獲取的端點 URL
,以及一個可以用來配置請求的選項對象。
options: {
headers?: HttpHeaders | {[header: string]: string | string[]},
observe?: 'body' | 'events' | 'response',
params?: HttpParams|{[param: string]: string | string[]},
reportProgress?: boolean,
responseType?: 'arraybuffer'|'blob'|'json'|'text',
withCredentials?: boolean,
}
這些重要的選項包括 observe
和 responseType
屬性。
observe
選項用于指定要返回的響應內容。responseType
選項指定返回數據的格式。你可以使用
options
對象來配置傳出請求的各個方面。例如,在Adding headers
中,該服務使用headers
選項屬性設置默認頭。
使用
params
屬性可以配置帶 HTTP URL 參數的請求,reportProgress
選項可以在傳輸大量數據時監(jiān)聽進度事件。
應用經常會從服務器請求 JSON 數據。在 ConfigService
例子中,該應用需要服務器 "config.json" 上的一個配置文件來指定資源的 URL
。
Path:"assets/config.json" 。
{
"heroesUrl": "api/heroes",
"textfile": "assets/textfile.txt"
}
要獲取這類數據,get()
調用需要以下幾個選項: {observe: 'body', responseType: 'json'}。這些是這些選項的默認值,所以下面的例子不會傳遞 options
對象。后面幾節(jié)展示了一些額外的選項。
這個例子符合通過定義一個可重用的可注入服務來執(zhí)行數據處理功能來創(chuàng)建可伸縮解決方案的最佳實踐。除了提取數據外,該服務還可以對數據進行后處理,添加錯誤處理,并添加重試邏輯。
ConfigService
使用 HttpClient.get()
方法獲取這個文件。
Path:"app/config/config.service.ts (getConfig v.1)" 。
configUrl = 'assets/config.json';
getConfig() {
return this.http.get(this.configUrl);
}
ConfigComponent
注入了 ConfigService
并調用了 getConfig
服務方法。
由于該服務方法返回了一個 Observable
配置數據,該組件會訂閱該方法的返回值。訂閱回調只會對后處理進行最少量的處理。它會把數據字段復制到組件的 config
對象中,該對象在組件模板中是數據綁定的,用于顯示。
Path:"app/config/config.component.ts (showConfig v.1)" 。
showConfig() {
this.configService.getConfig()
.subscribe((data: Config) => this.config = {
heroesUrl: data['heroesUrl'],
textfile: data['textfile']
});
}
你可以構造自己的 HttpClient
請求來聲明響應對象的類型,以便讓輸出更容易、更明確。所指定的響應類型會在編譯時充當類型斷言。
注:
- 指定響應類型是在向 TypeScript 聲明,它應該把你的響應對象當做給定類型來使用。這是一種構建期檢查,它并不能保證服務器會實際給出這種類型的響應對象。該服務器需要自己確保返回服務器 API 中指定的類型。
要指定響應對象類型,首先要定義一個具有必需屬性的接口。這里要使用接口而不是類,因為響應對象是普通對象,無法自動轉換成類的實例。
export interface Config {
heroesUrl: string;
textfile: string;
}
接下來,在服務器中把該接口指定為 HttpClient.get()
調用的類型參數。
Path:"app/config/config.service.ts (getConfig v.2)" 。
getConfig() {
// now returns an Observable of Config
return this.http.get<Config>(this.configUrl);
}
當把接口作為類型參數傳給
HttpClient.get()
方法時,你可以使用RxJS map 操作符來根據 UI 的需求轉換響應數據。然后,把轉換后的數據傳給異步管道。
修改后的組件方法,其回調函數中獲取一個帶類型的對象,它易于使用,且消費起來更安全:
Path:"app/config/config.component.ts (showConfig v.2)" 。
config: Config;
showConfig() {
this.configService.getConfig()
// clone the data object, using its known Config shape
.subscribe((data: Config) => this.config = { ...data });
}
要訪問接口中定義的屬性,必須將從 JSON 獲得的普通對象顯式轉換為所需的響應類型。例如,以下 subscribe
回調會將 data
作為對象接收,然后進行類型轉換以訪問屬性。
.subscribe(data => this.config = {
heroesUrl: (data as any).heroesUrl,
textfile: (data as any).textfile,
});
OBSERVE
和 RESPONSE
的類型是字符串的聯(lián)合類型,而不是普通的字符串。
options: {
...
observe?: 'body' | 'events' | 'response',
...
responseType?: 'arraybuffer'|'blob'|'json'|'text',
...
}
這會引起混亂。例如:
// this works
client.get('/foo', {responseType: 'text'})
// but this does NOT work
const options = {
responseType: 'text',
};
client.get('/foo', options)
在第二種情況下,TypeScript 會把 options
的類型推斷為 {responseType: string}
。該類型的 HttpClient.get
太寬泛,無法傳遞給 HttpClient.get
,它希望 responseType
的類型是特定的字符串之一。而 HttpClient
就是以這種方式顯式輸入的,因此編譯器可以根據你提供的選項報告正確的返回類型。
使用 as const
,可以讓 TypeScript 知道你并不是真的要使用字面字符串類型:
const options = {
responseType: 'text' as const,
};
client.get('/foo', options);
在前面的例子中,對 HttpClient.get()
的調用沒有指定任何選項。默認情況下,它返回了響應體中包含的 JSON 數據。
你可能還需要關于這次對話的更多信息。比如,有時候服務器會返回一個特殊的響應頭或狀態(tài)碼,來指出某些在應用的工作流程中很重要的條件。
可以用 get()
方法的 observe
選項來告訴 HttpClient
,你想要完整的響應對象:
getConfigResponse(): Observable<HttpResponse<Config>> {
return this.http.get<Config>(
this.configUrl, { observe: 'response' });
}
現(xiàn)在,HttpClient.get()
會返回一個 HttpResponse
類型的 Observable
,而不只是 JSON 數據。
該組件的 showConfigResponse()
方法會像顯示配置數據一樣顯示響應頭:
Path:"app/config/config.component.ts (showConfigResponse)" 。
showConfigResponse() {
this.configService.getConfigResponse()
// resp is of type `HttpResponse<Config>`
.subscribe(resp => {
// display its headers
const keys = resp.headers.keys();
this.headers = keys.map(key =>
`${key}: ${resp.headers.get(key)}`);
// access the body directly, which is typed as `Config`.
this.config = { ... resp.body };
});
}
注:
- 該響應對象具有一個帶有正確類型的
body
屬性。
當服務器不支持 CORS
協(xié)議時,應用程序可以使用 HttpClient
跨域發(fā)出 JSONP 請求。
Angular 的 JSONP 請求會返回一個 Observable
。 遵循訂閱可觀察對象變量的模式,并在使用async
管道管理結果之前,使用 RxJS map 操作符轉換響應。
在 Angular 中,通過在 NgModule
的 imports
中包含 HttpClientJsonpModule
來使用 JSONP。在以下示例中,searchHeroes()
方法使用 JSONP 請求來查詢名稱包含搜索詞的英雄。
/* GET heroes whose name contains search term */
searchHeroes(term: string): Observable {
term = term.trim();
let heroesURL = `${this.heroesURL}?${term}`;
return this.http.jsonp(heroesUrl, 'callback').pipe(
catchError(this.handleError('searchHeroes', [])) // then handle the error
);
};
該請求將 heroesURL
作為第一個參數,并將回調函數名稱作為第二個參數。響應被包裝在回調函數中,該函數接受 JSONP 方法返回的可觀察對象,并將它們通過管道傳給錯誤處理程序。
不是所有的 API 都會返回 JSON 數據。在下面這個例子中,DownloaderService
中的方法會從服務器讀取文本文件, 并把文件的內容記錄下來,然后把這些內容使用 Observable<string>
的形式返回給調用者。
Path:"app/downloader/downloader.service.ts (getTextFile)" 。
getTextFile(filename: string) {
// The Observable returned by get() is of type Observable<string>
// because a text response was specified.
// There's no need to pass a <string> type parameter to get().
return this.http.get(filename, {responseType: 'text'})
.pipe(
tap( // Log the result or error
data => this.log(filename, data),
error => this.logError(filename, error)
)
);
}
這里的 HttpClient.get()
返回字符串而不是默認的 JSON 對象,因為它的 responseType
選項是 'text'
。
RxJS 的 tap
操作符(如“竊聽”中所述)使代碼可以檢查通過可觀察對象的成功值和錯誤值,而不會干擾它們。
在 DownloaderComponent
中的 download()
方法通過訂閱這個服務中的方法來發(fā)起一次請求。
Path:"app/downloader/downloader.component.ts (download)" 。
download() {
this.downloaderService.getTextFile('assets/textfile.txt')
.subscribe(results => this.contents = results);
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: