
- 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 - GET 請求
- 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 NgModule
- 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 - JSON-P
HttpClient jsonp() 方法
JSONP 是一種特殊的技術,用於繞過 Web 瀏覽器強制執行的跨域 (CORS) 策略。通常情況下,瀏覽器只支援同一個域內網站的 AJAX 呼叫。要支援對另一個域的 AJAX 呼叫,CORS 策略必須在伺服器端和客戶端(瀏覽器)都啟用。
與其啟用 CORS 策略,伺服器可以傳送 JSONP 格式的響應。JSONP 格式基本上是用回撥函式包裝的 JSON。瀏覽器將從伺服器獲取響應並將其作為指令碼執行。回撥函式將獲取響應並執行必要的業務邏輯。
伺服器可以透過用回撥函式(例如 mycallback)包裝 JSON 格式的響應將其轉換為 JSONP 格式,如下所示:
mycallback( { ... json data ... })
這裡:
mycallback 是瀏覽器(客戶端)傳送的函式名稱。
jsonp() 是 HttpClient 類中可用的方法,用於使用 jsonp 技術請求伺服器。它類似於 get() 方法,但增加了一個選項,用於設定伺服器用來獲取回撥函式的查詢引數的名稱。Angular 將自動生成一個函式來解析客戶端的 JSON。然後,它將向 url 新增新的查詢引數。查詢引數的名稱將是在 jsonp 呼叫中設定的名稱。查詢引數的值是 Angular 自動生成的函式的名稱。
jsonp() 方法的簽名
jsonp() 方法的簽名如下:
jsonp(<url as string>, <callback>)
url 表示要請求的資源的 URI。
callback 表示在 jsonp 伺服器呼叫後要呼叫的回撥函式名稱(將自動生成)。
演示 jsonp 方法的簡單程式碼如下:
let jsonp_req = this.http.jsonp<Expense[]>('https://:8000/api/jsonp/expense', 'callback'); jsonp_req.subscribe(data => this.expenses = data);
這裡:
this.http 是 HttpClient 例項。
jsonp() 是用於請求伺服器的方法。它不會直接請求伺服器。相反,它返回一個 Observable,可以透過訂閱它來請求伺服器,並在訂閱函式中獲取實際的響應。
https:///api/jsonp/expense 是資源的 URI(統一資源識別符號)
Angular 將自動生成一個函式,例如 ng_jsonp_callback_0,並使用 jsonp() 函式的第二個引數將其附加到請求 url。
https://:8000/api/jsonp/expense?callback=ng_jsonp_callback_0
工作示例
為了實現 HTTP 客戶端-伺服器通訊,我們需要設定一個 Web 應用程式並公開一組 Web API。客戶端可以請求 Web API。讓我們建立一個示例伺服器應用程式,Expense API App,為支出提供 CRUD REST API(主要是 jsonp 請求)。
步驟 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/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.use(function (req, res) { res.status(404); });
在這裡,程式碼將建立以下六個提到的 REST API 端點。
/ 端點返回 OK 訊息,以確保應用程式正常工作。
/api/jsonp/expense 端點以 jsonp 格式返回資料庫中所有可用的支出專案。
步驟 8:執行應用程式,如下所示:
node index.js
步驟 9:要測試應用程式並確保其正常工作,請開啟瀏覽器並訪問 https://:8000/。如果應用程式正常工作,則應返回以下訊息。
{ "message": "Ok" }
讓我們建立一個可工作的 Angular 示例,以使用 HttpClient 服務類和 get() 方法從上述伺服器應用程式獲取所有支出專案。
步驟 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, HttpClientJsonpModule} from '@angular/common/http'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AppRoutingModule, HttpClientModule, HttpClientJsonpModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
這裡:
從 @angular/common/http 模組匯入 HttpClientModule 和 HttpClientJsonpModule。
將 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:透過傳遞 url 和選項來呼叫 this.http(HttpClient 例項)物件的 get 方法,並從伺服器獲取支出物件。然後,將支出設定到我們的區域性變數 expenses 中。
export class ListExpensesComponent implements OnInit{ expenses: Expense[] = []; constructor(private http: HttpClient) { } ngOnInit(): void { this.http.jsonp<Expense[]>('https://:8000/api/jsonp/expense', 'callback') .subscribe( data => { this.expenses = data as Expense[] console.log(this.expenses) }) } }
這裡:
將 Expense[] 設定為伺服器返回的物件的型別。伺服器將在其主體中以 JSON 格式傳送支出物件的陣列。
訂閱請求 (this.http.jsonp) 物件。然後將訂閱的資料解析為支出物件的陣列,並將其設定為區域性支出變數 (this.expenses)
步驟 10: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 { this.http.jsonp<Expense[]>('https://:8000/api/jsonp/expense', 'callback') .subscribe( data => { this.expenses = data as Expense[] console.log(this.expenses) }) } }
步驟 11:接下來,從元件獲取 expenses 物件並在我們的元件模板頁面 (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>
步驟 12:最後,使用以下命令執行應用程式:
ng serve
步驟 13:開啟瀏覽器並導航到 https://:4200/ url 並檢查輸出

在這裡,輸出顯示我們的支出作為專案列表。
結論
Angular 提供了一種簡單的方法來透過 HttpClient 物件請求伺服器。jsonp() 是一個特定方法,用於即使伺服器不支援跨域 API 呼叫 (CORS) 也能從伺服器獲取資源。