
- Angular 教程
- Angular - 首頁
- Angular - 概述
- Angular - 特性
- Angular - 優點與缺點
- Angular 基礎
- Angular - 環境設定
- Angular - 第一個應用程式
- Angular - MVC 架構
- Angular 元件
- Angular - 元件
- Angular - 元件生命週期
- Angular - 檢視封裝
- Angular - 元件互動
- Angular - 元件樣式
- Angular - 巢狀元件
- Angular - 內容投影
- Angular - 動態元件
- Angular - 元素
- Angular 模板
- Angular - 模板
- Angular - 文字插值
- Angular - 模板語句
- Angular - 模板中的變數
- Angular - SVG 作為模板
- Angular 繫結
- Angular - 繫結及其型別
- Angular - 資料繫結
- Angular - 事件繫結
- Angular - 屬性繫結
- Angular - 屬性繫結
- Angular - 類和樣式繫結
- Angular 指令
- Angular - 指令
- Angular - 內建指令
- Angular 管道
- Angular - 管道
- Angular - 使用管道轉換資料
- Angular 依賴注入
- Angular - 依賴注入
- Angular HTTP 客戶端程式設計
- Angular - 服務
- Angular - HTTP 客戶端
- Angular - 請求
- Angular - 響應
- Angular - 獲取
- Angular - PUT
- Angular - DELETE
- Angular - JSON-P
- Angular - 使用 HTTP 進行 CRUD 操作
- Angular 路由
- Angular - 路由
- Angular - 導航
- Angular - Angular Material
- Angular 動畫
- Angular - 動畫
- Angular 表單
- Angular - 表單
- Angular - 表單驗證
- Angular Service Workers 和 PWA
- Angular - Service Workers 和 PWA
- Angular 測試
- Angular - 測試概述
- Angular NgModules
- Angular - 模組簡介
- Angular 高階
- Angular - 身份驗證和授權
- Angular - 國際化
- Angular - 可訪問性
- Angular - Web Workers
- Angular - 伺服器端渲染
- Angular - Ivy 編譯器
- Angular - 使用 Bazel 構建
- Angular - 向後相容性
- Angular - 響應式程式設計
- Angular - 在指令和元件之間共享資料
- Angular 工具
- Angular - CLI
- Angular 雜項
- Angular - 第三方控制元件
- Angular - 配置
- Angular - 顯示資料
- Angular - 裝飾器和元資料
- Angular - 基本示例
- Angular - 錯誤處理
- Angular - 測試和構建專案
- Angular - 生命週期鉤子
- Angular - 使用者輸入
- Angular - 有什麼新功能?
- Angular 有用資源
- Angular - 快速指南
- Angular - 有用資源
- Angular - 討論
Angular - 請求
Http 請求
在 Http 協議中,請求是指客戶端應用程式啟動與伺服器通訊的過程。在本章中,我們將瞭解如何在 Angular 框架中向伺服器傳送請求,以及請求階段可用的選項。
設定伺服器應用程式
為了實現 HTTP 客戶端-伺服器通訊,我們需要設定一個 Web 應用程式,並需要公開一組 Web API。可以從客戶端請求 Web API。讓我們建立一個示例伺服器應用程式 Expense API App,為費用提供 CRUD REST API。
步驟 1:轉到您喜歡的 workspace,如下所示:
cd /go/to/your/favorite/workspace
步驟 2:建立一個新資料夾 expense-rest-api 並移動到該資料夾中
mkdir expense-rest-api && cd expense-rest-api
步驟 3:使用 npm 命令提供的 init 子命令建立一個新應用程式,如下所示:
npm init
上述命令會詢問一些問題,並使用預設答案回答所有問題。
步驟 4:安裝 express 和 cors 包以建立基於節點的 Web 應用程式。
npm install express cors --save
步驟 5:安裝 sqlite 包以將費用儲存在基於 sqlite 的資料庫中
npm install sqlite3 --save
步驟 6:建立一個新檔案 sqlitedb.js 並新增以下程式碼以使用費用表和示例費用條目初始化資料庫。費用表將用於儲存費用專案
var sqlite3 = require('sqlite3').verbose() const DBSOURCE = "expensedb.sqlite" let db = new sqlite3.Database(DBSOURCE, (err) => { if (err) { console.error(err.message) throw err }else{ console.log('Connected to the SQLite database.') db.run(`CREATE TABLE IF NOT EXISTS expense ( id INTEGER PRIMARY KEY AUTOINCREMENT, item text, amount real, category text, location text, spendOn text, createdOn text )`, (err) => { if (err) { console.log(err); }else{ var insert = 'INSERT INTO expense (item, amount, category, location, spendOn, createdOn) VALUES (?,?,?,?,?,?)' db.run(insert, ['Pizza', 10, 'Food', 'KFC', '2020-05-26 10:10', '2020-05-26 10:10']) db.run(insert, ['Pizza', 9, 'Food', 'Mcdonald', '2020-05-28 11:10', '2020-05-28 11:10']) db.run(insert, ['Pizza', 12, 'Food', 'Mcdonald', '2020-05-29 09:22', '2020-05-29 09:22']) db.run(insert, ['Pizza', 15, 'Food', 'KFC', '2020-06-06 16:18', '2020-06-06 16:18']) db.run(insert, ['Pizza', 14, 'Food', 'Mcdonald', '2020-06-01 18:14', '2020-05-01 18:14']) } } ); } }); module.exports = db
步驟 7:開啟 index.js 並更新以下程式碼:
var express = require("express") var cors = require('cors') var db = require("./sqlitedb.js") var app = express() app.use(cors()); var bodyParser = require("body-parser"); app.use(express.urlencoded({ extended: true })); app.use(express.json()); var HTTP_PORT = 8000 app.listen(HTTP_PORT, () => { console.log("Server running on port %PORT%".replace("%PORT%", HTTP_PORT)) }); app.get("/", (req, res, next) => { res.json({ "message": "Ok" }) }); app.get("/api/expense", (req, res, next) => { var sql = "select * from expense" var params = [] db.all(sql, params, (err, rows) => { if (err) { res.status(400).json({ "error": err.message }); return; } res.json(rows) }); }); app.get("/api/jsonp/expense", (req, res, next) => { var sql = "select * from expense" var params = [] db.all(sql, params, (err, rows) => { if (err) { res.status(400).json({ "error": err.message }); return; } res.jsonp(rows) }); }); app.get("/api/expense/:id", (req, res, next) => { var sql = "select * from expense where id = ?" var params = [req.params.id] db.get(sql, params, (err, row) => { if (err) { res.status(400).json({ "error": err.message }); return; } res.json(row) }); }); app.post("/api/expense/", (req, res, next) => { var errors = [] if (!req.body.item) { errors.push("No item specified"); } var data = { item: req.body.item, amount: req.body.amount, category: req.body.category, location: req.body.location, spendOn: req.body.spendOn, createdOn: req.body.createdOn, } var sql = 'INSERT INTO expense (item, amount, category, location, spendOn, createdOn) VALUES (?,?,?,?,?,?)' var params = [data.item, data.amount, data.category, data.location, data.spendOn, data.createdOn] db.run(sql, params, function (err, result) { if (err) { res.status(400).json({ "error": err.message }) return; } data.id = this.lastID; res.json(data); }); }) app.post("/api/expense/:id/update_amount", (req, res, next) => { var errors = [] if (!req.params.id) { errors.push("No item specified"); } var sql = 'UPDATE expense SET amount = ? WHERE id = ?' var params = [req.body.amount, req.params.id] db.run(sql, params, function (err, result) { if (err) { res.status(400).json({ "error": err.message }) return; } res.json({ id: req.params.id, amount: req.body.amount }); }); }) app.put("/api/expense/:id", (req, res, next) => { if (req.params.id == null) { res.status(400).json({ "error": "Resource (Expense) Id is not send." }) return } var data = { id: req.params.id, item: req.body.item, amount: req.body.amount, category: req.body.category, location: req.body.location, spendOn: req.body.spendOn } var sql = 'SELECT count(*) AS cnt FROM expense WHERE id = ?' var params = [data.id] db.get(sql, params, function (err, result) { if (err) { res.status(400).json({ "error": err.message }) return; } if (result.cnt == 0) { var sql = 'INSERT INTO expense (id, item, amount, category, location, spendOn, createdOn) VALUES (?, ?,?,?,?,?,?)' var params = [data.id, data.item, data.amount, data.category, data.location, data.spendOn, data.createdOn] db.run(sql, params, function (err, result) { if (err) { res.status(400).json({ "error": err.message }) return; } console.log(result) res.json(data); }); } else { db.run( `UPDATE expense SET item = ?, amount = ?, category = ?, location = ?, spendOn = ? WHERE id = ?`, [data.item, data.amount, data.category, data.location, data.spendOn, data.id], function (err, result) { if (err) { console.log(err); res.status(400).json({ "error": res.message }) return; } res.json(data) }); } }); }) app.delete("/api/expense/:id", (req, res, next) => { db.run( 'DELETE FROM expense WHERE id = ?', req.params.id, function (err, result) { if (err) { res.status(400).json({ "error": res.message }) return; } res.json({ "message": "deleted", changes: this.changes }) }); }) app.use(function (req, res) { res.status(404); });
這裡,程式碼將建立以下六個提到的 REST API 端點
/ 端點返回一個 OK 訊息以確保應用程式正常工作
/api/expense 端點返回資料庫中所有可用的費用專案
/api/jsonp/expense 端點以 jsonp 格式返回資料庫中所有可用的費用專案
/api/expense/:id 端點根據費用條目 ID 返回費用條目
/api/expense/:id 端點使用 put 方法將根據費用條目 ID 更新費用條目
/api/expense 端點使用 post 方法將新的費用條目新增到資料庫中
/api/expense/:id/update_amount 端點使用 post 方法將更新 URL 中指定的費用條目的金額
/api/expense/:id 端點使用 delete 方法將根據費用條目 ID 刪除費用條目
步驟 8:執行應用程式,如下所示:
node index.js
步驟 9:要測試應用程式並確保它正常工作,請開啟瀏覽器並轉到https://:8000/。如果應用程式正常工作,它應該返回以下訊息。
{ "message": "Ok" }
設定 HttpClient 服務
在開始 http 請求之前,我們需要在應用程式中正確設定 HttpClient 服務。Angular 為 http 通訊提供了一個單獨的模組 HttpClientModule,其中包含 HttpClient 服務。要使用 HttpClient 服務,應將 HttpClientModule 匯入到應用程式中,無論是在應用程式的根/模組配置部分。
步驟 1:要在獨立應用程式(元件)中匯入 HttpClientModule,請在根配置中使用 importProvidersFrom 方法,如下所示:
import { bootstrapApplication } from '@angular/platform-browser'; import { HttpClientModule } from '@angular/common/http'; import { importProvidersFrom } from '@angular/core'; import {AppComponent} from './app/app.component'; bootstrapApplication(AppComponent, { providers: [ importProvidersFrom(HttpClientModule), ] });
這裡,
importProvidersFrom 方法是從 angular core 包匯入的。它匯入 HttpClientModule 中包含的所有提供程式
步驟 2:要在 Web 應用程式中匯入 HttpClientModule,請在根/相應模組檔案中 imports 陣列中匯入 HttpClientModule 模組,如下所示:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { HttpClientModule } from '@angular/common/http'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AppRoutingModule, HttpClientModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
匯入 http 模組將在 Angular 依賴注入設定中包含 HttpClient 服務,以便可以根據需要將 HttpClient 注入到任何 Angular 元件中,如下所示:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Injectable() export class MyService { constructor(private http: HttpClient) { } }
請求/響應工作流程
HttpClient 提供了幾種方法來啟動 http 請求。基本上,所有方法都返回一個帶有可選型別變數的可觀察物件 (Observable<T>)。可以訂閱可觀察物件以啟動請求。一旦訂閱了可觀察物件,它就會啟動請求並將其傳遞給一系列已註冊的攔截器,最後到達伺服器。然後,它從伺服器接收響應並將其釋出到已訂閱的函式。
請求的工作流程如下:
使用者建立一個新的 HttpClient 例項,例如透過元件的建構函式建立 http。
constructor(private http: HttpClient) { }
使用者透過傳遞資源資訊來呼叫任何一個 HttpClient 方法,例如 request()。
let req = this.http.request(<action>, <url>, <body>, <option>)
request() 方法將使用給定的資源資訊建立一個可觀察物件,例如 req。
let req = this.http.request(<action>, <url>, <body>, <option>)
使用者將使用 subscribe() 方法將回調函式訂閱到可觀察物件。
req.subscribe((data) => console.log(data));
一旦使用者訂閱了 Observable,它就會將請求傳遞給已註冊的攔截器,其順序與攔截器的註冊順序相同。
一旦請求透過所有已註冊的攔截器,Observable 將向伺服器傳送請求。
Observable 等待伺服器響應,一旦從伺服器接收到響應,它就會將響應返回給已訂閱的函式
已訂閱的函式將執行必要的業務邏輯並將輸出設定為元件的變數。
元件將使用 HttpClient 的輸出呈現其模板。
一個示例請求如下:
let req = this.http.request('GET', 'https://:8000/api/expense/1') req.subscribe(data => this.myexpense = data);
這裡,
this.http 是 HttpClient 例項
request() 是用於建立可觀察物件的方法,當訂閱時,它會啟動請求。
subscribe() 是用於訂閱返回的可觀察物件並隨後啟動請求和獲取響應的方法。
最後,subscribe 方法的引數是用於獲取實際響應主體內容的回撥函式。
HttpClient 引數
HttpClient 方法支援的引數如下:
資源 URI - 它基本上是表示資源的 URL/端點。
請求正文 - 它基本上是與請求一起傳送到伺服器的資料。資料可以是查詢字串格式或 json 格式。
請求選項 - 它基本上是與請求一起傳送的所有其他資料。它包含查詢字串、標題、cookie 等。
資源 URI
所有方法都接受 url/端點作為引數之一。它表示要從伺服器獲取的資源。在我們的示例應用程式中,url 以 https://:8000/ 開頭,一個可能的選項是 https://:8000/api/expenses。此端點將從伺服器獲取所有費用並以 json 格式將其傳送回客戶端。
請求正文
所有方法都接受 body 作為引數之一。body 引數在某些方法中是可選的。請求的正文將支援不同的格式,它將在請求的標頭 Content-Type 中使用 MIME 型別指定。最常見的資料型別如下:
表單資料。MIME 型別為 application/x-www-form-urlencoded
帶有上傳的表單資料。MIME 型別為 multipart/form-data
純文字。MIME 型別為 text/plain
JSON。MIME 型別為 application/json
HttpParams 類
表單資料可以使用 Angular 提供的 HttpParams 類建立。HttpParams 以查詢字串格式接受資料(鍵/值作為 key=value,每個鍵/值用 & 分隔)。它具有將一個或多個引數作為序列新增的方法,方法是將方法連結在一起。所有方法都建立例項的副本,並在複製的例項中新增/刪除引數(鍵/值對),並將其返回。
HttpParams 建構函式的簽名如下:
constructor(options: HttpParamsOptions = {} as HttpParamsOptions)
其中,
HttpParamsOptions 物件可以透過以下屬性建立:
- fromString?: string
- fromObject?: {…}
使用建構函式建立 HttpParams 物件的示例程式碼如下:
/* using fromString option */ let httpParams = new HttpParams( { fromString: 'a=b*b=c' } ) /* using fromObject option */ let httpParams = new HttpParams( { fromObject: { a: "b", c: "d" } )
HttpParams 支援的方法如下:
set(): 接收一個引數和值。新增一個具有給定值的新引數。
delete(): 接收一個引數。刪除給定的引數。
has(): 接收一個引數。根據給定引數是否存在返回 true/false。
keys(): 不接收任何引數。返回所有引數。
get(): 接收一個引數。返回給定引數的第一個值。
getAll(): 接收一個引數。返回給定引數的所有值。
append(): 接收一個引數。將值新增到給定引數。
appendAll(): 接收一個包含多個引數的物件。將值新增到所有引數。
toString(): 不接收任何引數。以查詢字串格式返回物件。
建立 HttpParams 物件的示例程式碼如下:
let formData = new HttpParams(); formData = formData .set('item', 'Modified') .set('amount', 25); console.log(formData.toString()) // item=Modified&amount=25
請求選項
無論使用何種方法,options 都是所有方法都接受的一個通用引數,用於表示請求選項。options 是一個包含標準請求資料的 JavaScript 物件(或雜湊表)。options 可以包含以下條目,並表示請求和響應的不同方面。
- observe
- responseType
- headers
- params
- context
- reportProgress
- withCredentials
- transferCache
讓我們在接下來的章節中逐一學習。
observe
observe 用於指定在伺服器通訊期間需要觀察響應的哪一部分,並將資料傳送回訂閱函式。根據 observe 選項,將返回完整的響應或部分響應。可能的值有 events、body 和 response。
events
events 用於返回伺服器響應流中觸發的事件。它將響應作為 Observable<HttpEvent> 型別返回。這裡,R 是要返回的實際資料(響應體)的型別。
let req = this.http.request<Expense>( 'GET', 'https://:8000/api/expense/1', { observe: 'events', responseType : 'json' });
這裡,
json 是用於解釋響應體的格式。
Expense 是用於轉換和返回響應體的型別。否則,它將以通用的 JavaScript 物件形式返回響應體。
response
response 用於返回伺服器的完整響應。它將響應作為 Observable<HttpResponse> 型別返回。這裡,R 是要返回的實際資料(響應體)的型別。
let req = this.http.request<Expense>( 'GET', 'https://:8000/api/expense/1', { observe: 'response', responseType : 'json' });
這裡,
json 是用於解釋響應體的格式。
expense 是用於轉換和返回響應體的型別。否則,它將以通用的 JavaScript 物件形式返回響應體。
body
body 用於僅返回伺服器響應的正文內容。它將響應作為 Observable 型別返回,這裡,R 是要返回的實際資料(響應體)的型別。
let req = this.http.request<Expense>( 'GET','https://:8000/api/expense/1', { observe: 'body', responseType : 'json' });
這裡,
json 是用於解釋響應體的格式。
Expense 是用於轉換和返回響應體的型別。否則,它將以通用的 JavaScript 物件形式返回響應體。
responseType
responseType 用於解釋響應體。它可以具有以下四個可能的值:
- arraybuffer
- blob
- text
- json
讓我們逐一瞭解這些選項。
arraybuffer
arraybuffer 用於將響應體解釋為通用的原始二進位制資料緩衝區並返回 Observable。它可用於流式傳輸音訊/影片內容。
let req = this.http.request<Expense>( 'GET', 'https://:8000/api/expense/1', { observe: 'body', responseType : 'arraybuffer' });
body
blob 用於將響應體解釋為二進位制格式並返回 Observable。它可用於下載大型檔案。
let req = this.http.request<Expense>( 'GET', 'https://:8000/api/expense/1', { observe: 'body', responseType : 'blob' });
text
text 用於將響應體解釋為純文字格式並返回 Observable。它可用於表示基於文字的資料。
let req = this.http.request<Expense>( 'GET', 'https://:8000/api/expense/1', { observe: 'body', responseType : 'text' });
json
json 用於將響應體解釋為 json 格式並返回 Observable,其中 R 是請求的資料型別 (Expense)。它可用於以 json 格式表示結果。透過在方法中指定型別變數 (R),可以將其進一步編碼為任何型別,如下所示:
let req = this.http.request<Expense>( 'GET', 'https://:8000/api/expense/1', { observe: 'body', responseType : 'json' });
根據 observe 和 responseType,Httpclient 將返回具有不同型別變數的 Observable。讓我們檢查 observe 和 responseType 的一些組合以更好地理解這個概念。
-
observe => body 和 responseType => json
返回 Observable。R 表示型別變數。
-
observe => response 和 responseType => json
返回 Observable<HttpResponse>。R 表示型別變數並編碼響應體。
-
observe => events 和 responseType => json
返回 Observable<HttpEvent>。R 表示型別變數並編碼響應體。
-
observe => events 和 responseType => arraybuffer
返回 Observable<HttpEvent>。響應體被編碼為 ArrayBuffer。
-
observe => response 和 responseType => blob
返回 Observable<HttpEvent>。響應體被編碼為 ArrayBuffer。
-
observe => response 和 responseType => text
返回 Observable<HttpResponse>。響應體被編碼為 ArrayBuffer。
我們可以根據需要組合 observe 和 responseType 來建立更多組合。
headers
headers 用於指定 HTTP 標頭。它可以包含標準的 http 標頭作為鍵/值對,也可以使用 HttpHeaders 類對資料進行編碼。一個鍵/值對的示例標頭如下所示:
{ 'Content-type': 'application/json' }
它指定請求內容型別為 json。
Angular 提供了一個特殊的類 HttpHeaders 來組合標頭詳細資訊。它接受匿名物件作為標頭資訊並初始化它。它具有方法(set()、append()、delete() 等),可以透過將方法連結在一起,依次新增/刪除一個或多個標頭。所有方法都會建立例項的副本,並在副本中新增/刪除標頭資訊,並返回它。
let httpHeaders = new HttpHeaders( { 'Content-Type': 'application/json' }) httpHeaders = httpHeaders .set('Accept-Language', 'en-US,en;q=0.5') .set('Accept-Encoding', 'gzip, deflate, br'); let options = { 'headers': httpHeaders } let req = this.http.request<Expense>( 'GET', 'https://:8000/api/expense/1', options ); req.subscribe( (data: Expense) => this.myexpense = data );
這裡,
httpHeaders 是一個用於封裝要傳送到伺服器的 HTTP 標頭資訊的 物件。它是使用 HttpHeaders 類建立的。
options 是一個包含標頭資訊的增強物件。
HttpHeaders 支援的方法如下:
set(): 接收一個標頭和值。新增一個具有給定值的新標頭。
delete(): 接收一個標頭。刪除給定的引數。
has(): 接收一個引數。根據給定標頭是否存在返回 true/false。
keys(): 不接收任何引數。返回所有引數。
get(): 接收一個引數。返回給定引數的第一個值。
getAll(): 接收一個標頭。返回給定引數的所有值。
append(): 接收一個引數。將值新增到給定標頭。
appendAll(): 接收一個包含多個引數的物件。將值新增到所有標頭。
toString(): 不接收任何引數。以查詢字串格式返回物件。
params
params 允許使用 HttpParams 類設定查詢字串。請檢視請求正文部分以瞭解有關 HttpParams 類的更多資訊。
建立 HttpParams 物件並在請求中設定它的示例程式碼如下:
let formData = new HttpParams(); formData = formData .set('item', 'Modified') .set('amount', 25); console.log(formData.toString()) // item=Modified&amount=25 let req = this.http.request<Expense>('GET', 'https://:8000/api/expense/1', { observe: 'body', responseType : 'json', params: formData });
context
context 用於以型別安全的方式並避免鍵衝突的方式傳送任意鍵/值對。它用作攔截器的資訊源,攔截器充當客戶端和伺服器之間的中介軟體。Angular 提供了一個特殊的類 HttpContext 來編碼上下文資訊。一個上下文示例如下所示:
// create a key using HttpContextToken export const IS_AUTH_ENABLED = new HttpContextToken<boolean>(() => false); // set data for the context let authContext = new HttpContext().set(IS_AUTH_ENABLED, true) let req = this.http.request<Expense>('GET', 'https://:8000/api/expense/1', { observe: 'body', responseType : 'json', context: authContext });
這裡,
HttpContextToken 類用於建立上下文的鍵。它可以選擇指定值型別。
IS_AUTH_ENABLED 是鍵,其型別為布林值。
IS_AUTH_ENABLED 設定為 true。
我們可以使用 get() 方法透過傳遞令牌來獲取上下文值,如下所示:
let contextValue = req.context.get<boolean>(IS_AUTH_ENABLED) // true
reportProgress
reportProgress 用於指定是否從伺服器獲取請求(通訊)的進度。它可用於顯示透過 Web API 上傳大型檔案的進度。
let req = this.http.request<Expense>( 'GET', 'https://:8000/api/expense/1', { observe: 'events', responseType : 'json', reportProgress: true });
withCredentials
withCredential 用於指定是否應將請求與傳出憑據(cookie)一起傳送。它接受布林值。
this.http.request<Expense>( 'GET', 'https://:8000/api/expense/1', { observe: 'body', responseType : 'json' withCredentials: true });
transferCache
transferCache 用於指定是否應快取請求。它接受布林值或 HttpTransferCacheOptions 值。HttpTransferCacheOptions 用於編碼動態邏輯,以根據自定義篩選器函式篩選要快取的請求並覆蓋預設快取行為。
let req = this.http.request<Expense>( 'GET', 'https://:8000/api/expense/1', { observe: 'body', responseType : 'json', transferCache: true });
HttpClient 方法
HttpClient 類提供的用於客戶端-伺服器通訊的方法如下:
- request()
- head()
- get()
- post()
- put()
- patch()
- delete()
- jsonp()
- options()
我們將在本章中學習通用 request() 方法,並在後續章節中學習其他方法。
request() 方法
request() 是一個通用方法,用於使用所有可能的 HTTP 動詞(如 get、post、patch 等)向伺服器傳送請求。它有許多過載。讓我們檢查兩個主要的過載函式,一個使用泛型選項,另一個使用 HttpRequest 物件。
泛型選項 - 接收 url、http 動詞、正文內容和 options 物件。
HttpRequest 選項 - 接收 HttpRequest 物件。
HttpRequest 選項
Angular 提供了一個類 HttpRequest 來表示完整的 http 請求。它具有內建選項,可以包含 url、HTTP 方法/動詞、響應型別、標頭、引數等。
一個 HttpRequest 物件示例如下所示:
var httpRequest = new HttpRequest<Expense>('GET', 'https://:8000/api/expense/1', { responseType : 'json' });
這裡,
this.http 是 HttpClient 例項。
GET 方法用作 HTTP 動詞。
端點 (https:///api/expense/1) 將從伺服器返回 id 等於 1 的費用。
responseType 設定為 json。這將以 json 格式返回響應的正文。
上面的示例請求物件可以像下面這樣使用,以將請求傳送到伺服器:
var req = this.http.request<Expense>(httpRequest); req.subscribe(data : HttpEvent<Expense> => { this.myexpense = (data as HttpResponse<Expense>).body as Expense; }
這裡,
request() 返回 HttpEvent,它是多種型別的聯合,如下所示:
type HttpEvent<T> = HttpSentEvent | HttpHeaderResponse | HttpResponse<T> | HttpProgressEvent | HttpUserEvent<T>;
由於我們將 responseType 設定為 json 並將 Expense 設定為要返回的物件,因此 observable 將在正文中返回 HttpResponse<Expense>。因此,我們將返回的資料物件轉換為 HttpResponse<Expense> 物件,然後從 body 屬性獲取費用。
泛型選項
它按給定順序接收四個引數,如下所示:
- HTTP 方法/動詞
- url
- body(可選)
- options
一個示例請求如下:
let req = this.http.request<Expense>('GET', 'https://:8000/api/expense/1', { observe: 'body', responseType : 'json', }); req.subscribe(data => { this.myexpense = data });
工作示例
讓我們建立一個 Angular 工作示例,以使用 HttpClient 服務類和 HttpRequest 選項從伺服器獲取所有費用專案。
步驟 1:透過執行 ng new 命令建立一個新的 Angular 應用程式,如下所示:
ng new my-http-app
啟用 Angular 路由和 CSS,如下所示:
? Would you like to add Angular routing? Yes ? Which stylesheet format would you like to use? CSS
步驟 2:透過在模組配置檔案 (app.module.ts) 中匯入 HttpClientModule 來啟用應用程式中的 http 通訊。
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { HttpClientModule } from '@angular/common/http'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AppRoutingModule, HttpClientModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
這裡,
從 @angular/common/http 模組匯入 HttpClientModule。
將 HttpClientModule 新增到 @NgModule 配置的 imports 部分。
步驟 3:建立一個新的介面 Expense 來表示我們的費用專案。
interface Expense { id: Number, item: String, amount: Number, category: String, location: String, spendOn: Date } export default Expense;
步驟 4:建立一個新的元件 ListExpenses 來顯示來自伺服器的費用專案。
ng generate component ListExpenses
它將建立如下所示的元件:
CREATE src/app/list-expenses/list-expenses.component.css (0 bytes) CREATE src/app/list-expenses/list-expenses.component.html (28 bytes) CREATE src/app/list-expenses/list-expenses.component.spec.ts (602 bytes) CREATE src/app/list-expenses/list-expenses.component.ts (229 bytes) UPDATE src/app/app.module.ts (581 bytes)
步驟 5:將我們的新元件包含到 App 根元件的檢視 app.component.html 中,如下所示:
<app-list-expenses></app-list-expenses> <router-outlet></router-outlet>
步驟 6:透過建構函式將 HttpClient 注入到 ListExpenses 元件中,如下所示:
import { Component } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-list-expenses', templateUrl: './list-expenses.component.html', styleUrls: ['./list-expenses.component.css'] }) export class ListExpensesComponent { constructor(private http: HttpClient) { } }
步驟 7:實現 OnInit 生命週期鉤子,以便在 ListExpenses 元件初始化後向伺服器請求費用。
export class ListExpensesComponent implements OnInit{ constructor(private http: HttpClient) { } ngOnInit(): void { } }
步驟 8:建立一個區域性變數 expenses 來儲存來自伺服器的費用。
export class ListExpensesComponent implements OnInit{ expenses: Expense[] = []; constructor(private http: HttpClient) { } ngOnInit(): void { } }
步驟9:建立一個HttpRequest物件並設定費用端點的URL。
export class ListExpensesComponent implements OnInit{ expenses: Expense[] = []; constructor(private http: HttpClient) { } ngOnInit(): void { let req = new HttpRequest( 'GET', 'https://:8000/api/expense',{ responseType: 'json' } ) } }
這裡,
將GET設定為我們端點的HTTP方法
將https://:8000/api/expense設定為我們端點的URL
將json設定為responseType。這將把響應體解析為JSON格式。
步驟10:透過傳遞HttpRequest物件呼叫this.http(HttpClient例項)物件的request方法,並從伺服器獲取費用物件。然後,將費用設定到我們的本地變數expenses中。
export class ListExpensesComponent implements OnInit{ expenses: Expense[] = []; constructor(private http: HttpClient) { } ngOnInit(): void { let req = new HttpRequest( 'GET', 'https://:8000/api/expense',{ responseType: 'json' } ) this.http.request<Expense[]>(req) .subscribe((data : HttpEvent<Expense[]> )=> { this.expenses = (data as HttpResponse<Expense[]>).body as Expense[] console.log(this.expenses) }) } }
這裡,
將Expense[]設定為伺服器返回的物件的型別。伺服器將在其主體中以JSON格式傳送費用物件的陣列。
訂閱請求(this.http.request)物件。然後將訂閱的資料解析為費用物件的陣列,並將其設定為本地費用變數(this.expenses)
步驟11:ListExpensesComponent的完整程式碼如下:
import { Component, OnInit } from '@angular/core'; import { HttpClient, HttpRequest, HttpResponse, HttpEvent } from '@angular/common/http'; import Expense from '../Expense'; @Component({ selector: 'app-list-expenses', templateUrl: './list-expenses.component.html', styleUrls: ['./list-expenses.component.css'] }) export class ListExpensesComponent implements OnInit{ expenses: Expense[] = []; constructor(private http: HttpClient) { } ngOnInit(): void { let req = new HttpRequest( 'GET', 'https://:8000/api/expense',{ responseType: 'json' } ) this.http.request<Expense[]>(req) .subscribe((data : HttpEvent<Expense[]> )=> { this.expenses = (data as HttpResponse<Expense[]>).body as Expense[] console.log(this.expenses) }) } }
步驟12:接下來,從元件中獲取費用物件,並在我們的元件模板頁面(list-expenses.component.html)中渲染它。
<div><h3>Expenses</h3></div> <ul> <li *ngFor="let expense of expenses"> {{expense.item}} @ {{expense.location}} for {{expense.amount}} USD on {{expense.spendOn | date:'shortDate' }} </li> </ul>
步驟13:最後,使用以下命令執行應用程式:
ng serve
步驟14:開啟瀏覽器並導航到https://:4200/ URL,並檢查輸出。

在這裡,輸出顯示我們的費用作為專案列表。
步驟15:讓我們透過將HttpRequest選項更改為通用選項來修改上述示例應用程式。
步驟16:按如下所示更改ngOnInit方法:
ngOnInit(): void { this.http.request<Expense[]>('GET', 'https://:8000/api/expense', { observe : 'body', responseType : 'json' }) .subscribe( data => { this.expenses = data as Expense[] console.log(this.expenses) }) }
這裡,
刪除了HttpRequest物件
透過合併通用選項更改了request方法的引數
在第三個引數中設定observe選項為body。這將解析主體並僅返回主體,而不是整個響應。
更改了subscribe()方法,並將返回的資料設定為費用的陣列(Expense[])
步驟17:執行應用程式並確認輸出。輸出與上述示例相同。

結論
Angular 提供了一種透過HttpClient和HttpRequest物件請求伺服器的簡單方法。request()方法是一個通用方法,用於支援所有HTTP動詞,如GET、POST、PUT、DELETE等。我們將在後續章節中學習更多針對特定HTTP動詞的方法。