JS發(fā)起HTTP請求的多種方式總結(jié)
為了更好的理解HTTP協(xié)議先來了解一下IP和TCP協(xié)議。
- IP(Internet Protocol)協(xié)議和TCP(Transmission Control Protocol)協(xié)議是互聯(lián)網(wǎng)的基礎協(xié)議,它們位于網(wǎng)絡協(xié)議棧的較低層次,主要負責數(shù)據(jù)包的發(fā)送和接收。
- IP協(xié)議是網(wǎng)絡層的協(xié)議,主要負責將數(shù)據(jù)包發(fā)送到正確的設備。每個連接到互聯(lián)網(wǎng)的設備都有一個唯一的IP地址,IP協(xié)議就是通過這個地址將數(shù)據(jù)包發(fā)送到正確的設備。
- TCP協(xié)議是傳輸層的協(xié)議,主要負責在兩個設備之間建立可靠的連接,并保證數(shù)據(jù)包的順序和完整性。TCP協(xié)議會對數(shù)據(jù)包進行編號,確保接收端能夠按照正確的順序接收數(shù)據(jù)包,如果有數(shù)據(jù)包丟失,TCP協(xié)議還會要求發(fā)送端重新發(fā)送。
HTTP(HyperText Transfer Protocol)協(xié)議則位于應用層,它是建立在TCP協(xié)議之上的。HTTP協(xié)議定義了客戶端和服務器之間如何進行數(shù)據(jù)交換,例如請求的格式、響應的格式等。當在瀏覽器中輸入一個網(wǎng)址時,瀏覽器就會通過HTTP協(xié)議向服務器發(fā)送請求,并接收服務器的響應。
所以,HTTP協(xié)議依賴于TCP協(xié)議來傳輸數(shù)據(jù),而TCP協(xié)議又依賴于IP協(xié)議來將數(shù)據(jù)包發(fā)送到正確的設備。
筆者屬于前端開發(fā),接下來的一段時間要總結(jié)在前端開發(fā)領(lǐng)域處于戰(zhàn)略地位的知識點。HTTP請求就屬于前端戰(zhàn)略知識點之一。
本文來總結(jié)下發(fā)起HTTP的幾種方式。
使用 XMLHttpRequest
XMLHttpRequest是比較底層也比較早期的發(fā)起http請求的方式,XMLHttpRequest不是基于Promise的所以往往在使用XMLHttpRequest時需要手動封裝為Promise形式。
export const ajax = function (config) { return new Promise((resolve, reject) => { // 2. 發(fā)起XHR請求,默認請求方法為GET const xhr = new XMLHttpRequest() xhr.open(config.method || 'GET', config.url) xhr.setRequestHeader('Authorization', '2f3e1153a4ef0cc3a96fde17509a8a4b8cd428c5fbf0bf60e7133a1d3ca5a571'); xhr.setRequestHeader('Content-Type','application/json') xhr.responseType = 'blob'; xhr.addEventListener('loadend', () => { // 3. 調(diào)用成功/失敗的處理程序 if (xhr.status >= 200 && xhr.status < 300) { resolve(xhr.response) // typeof xhr.response === 'string' ? resolve(JSON.parse(xhr.response)) : resolve(xhr.response) } else { reject(new Error(xhr.response)) } }) xhr.send(JSON.stringify(config.data)) }) }
使用axios
axios實際是對XMLHttpRequest的封裝
axios({ method: 'post', url: 'https://api.example.com/data', data: { key: 'value' }, headers: { 'Content-Type': 'application/json' } }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });
使用Fetch
Fetch是比較現(xiàn)代的網(wǎng)絡請求接口,它也提供了一種跨網(wǎng)絡異步獲取資源。Fetch基于Promise設計。主要特點
- 基于Promise:返回的Promise對象,可以使用then方法進行鏈式調(diào)用,使得異步代碼更易于管理。
- 靈活性:Fetch可以自定義請求的各種設置,如請求方法(GET、POST等)、請求頭、請求體等。
- 支持跨域請求:Fetch支持CORS(跨源資源共享),可以進行跨域請求。
- 支持流處理:Fetch支持流處理,可以在數(shù)據(jù)完全接收到之前就開始處理數(shù)據(jù)。
基本使用
fetch('https://api.example.com/data') .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.log('Error:', error));
瀏覽器發(fā)起
瀏覽器作為web客戶端和服務端都屬于HTTP協(xié)議的設備。瀏覽器又通過HTTP協(xié)議與服務器發(fā)生交互,自然瀏覽器本身也具有發(fā)起HTTP請求的功能。
排除XMLHttpRequest、Fetch。瀏覽器自身還可以通過地址欄、通過html的相關(guān)標簽發(fā)起HTTP請求。
html標簽img、script、link、a、video、audio等都可以通過src或者href屬性發(fā)情HTTP請求,當然只能發(fā)起get請求。
還有html的form標簽,可以發(fā)起get和post請求。
使用cURL
cURL是一個命令行工具,它允許通過各種協(xié)議向服務器發(fā)送請求并接收響應。支持的協(xié)議非常多,包括 HTTP、HTTPS、FTP、FTPS、SFTP、SCP、LDAP、LDAPS、SMTP、POP3、IMAP、RTSP、RTMP、TELNET、TFTP等。
主要特點包括
- 支持多協(xié)議:如上所述,cURL 支持非常多的協(xié)議,可以滿足各種網(wǎng)絡請求的需求。
- 支持數(shù)據(jù)上傳和下載:cURL 可以用于文件的上傳和下載,非常適合進行批量操作。
- 支持 SSL 證書:cURL 支持 SSL 證書,可以進行安全的網(wǎng)絡請求。
- 支持代理:cURL 支持通過代理服務器進行網(wǎng)絡請求。
- 支持用戶認證:cURL 支持各種用戶認證方式,如基本認證、摘要認證、NTLM 認證等。
使用 cURL 發(fā)起一個 GET 請求
curl https://api.example.com/data
后端與后端之間
后端與后端之間也可以發(fā)起請求。這里java的HttpClient來發(fā)起HTTP的get請求
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class Main { public static void main(String[] args) throws Exception { HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(new URI("http://example.com")) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } }
上面首先創(chuàng)建了一個HttpClient對象,然后創(chuàng)建一個HttpRequest對象,指定了請求的URL。然后使用 HttpClient的send方法發(fā)送請求,并獲取到HttpResponse對象。
nginx中轉(zhuǎn)
nginx是比較知名的HTTP請求中間件。雖然不能直接發(fā)起HTTP,但可以作為代理,將請求做轉(zhuǎn)發(fā)。
一個簡單的Nginx配置示例,用于解決跨域問題
server { listen 80; server_name localhost; location /api/ { proxy_pass http://backend_server; # 這里是實際服務器的地址 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
上面設置了一個反向代理,將所有以 /api/
開頭的請求轉(zhuǎn)發(fā)給 http://backend_server
。這樣,前端就可以通過訪問 http://localhost/api/
來進行數(shù)據(jù)交互,而不會產(chǎn)生跨域問題。
小程序發(fā)起
微信小程序提供了wx.request
來發(fā)起HTTP請求
wx.request({ url: 'https://api.example.com/data', // 請求的 URL method: 'GET', // 請求方法 data: { // 請求參數(shù) key: 'value' }, header: { // 設置請求的 header 'content-type': 'application/json' }, success(res) { // 請求成功的回調(diào)函數(shù) console.log(res.data) }, fail(err) { // 請求失敗的回調(diào)函數(shù) console.error(err) } })
注意的是,由于微信小程序的安全策略,開發(fā)者需要在微信公眾平臺配置服務器域名,只有配置過的域名才能被微信小程序請求。此外,微信小程序不支持跨域請求,也不支持使用 Cookie。
android發(fā)起
在Android開發(fā)中,可以使用多種方式來發(fā)起HTTP請求,其中最常用的是使用OkHttp庫
// 創(chuàng)建 OkHttpClient OkHttpClient client = new OkHttpClient(); // 創(chuàng)建 Request Request request = new Request.Builder() .url("http://example.com") .build(); // 使用 OkHttpClient 發(fā)起請求 client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { final String myResponse = response.body().string(); MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { // 在這里更新 UI textView.setText(myResponse); } }); } } });
需要注意的是,網(wǎng)絡請求是在后臺線程中進行的,所以不能直接在回調(diào)函數(shù)中更新UI。需要使用 runOnUiThread
方法來在主線程中更新UI。
此外,由于Android不允許在主線程中進行網(wǎng)絡請求,所以這段代碼需要在后臺線程中運行。
Websocket
WebSocket的握手過程使用的是HTTP協(xié)議,但一旦握手成功,服務器與客戶端之間的交互就完全依賴于WebSocket協(xié)議了。所以嚴格來說Websocket不算HTTP請求。
WebSocket協(xié)議支持全雙工通信,即服務器和客戶端可以同時發(fā)送接收信息,而HTTP協(xié)議是半雙工的,即任一時刻要么是請求要么是響應,不能同時進行。
一個簡單的在瀏覽器中使用WebSocket的例子
// 創(chuàng)建 WebSocket 連接 var socket = new WebSocket('ws://localhost:8080'); // 連接打開時觸發(fā) socket.onopen = function(event) { console.log('WebSocket is connected.'); // 發(fā)送一個初始化消息 socket.send('Hello, Server!'); }; // 接收到消息時觸發(fā) socket.onmessage = function(event) { console.log('Received: ' + event.data); // 關(guān)閉連接 socket.close(); }; // 連接關(guān)閉時觸發(fā) socket.onclose = function(event) { console.log('WebSocket is closed.'); }; // 連接發(fā)生錯誤時觸發(fā) socket.onerror = function(error) { console.log('WebSocket Error: ' + error); };
到此這篇關(guān)于JS發(fā)起HTTP請求的多種方式總結(jié)的文章就介紹到這了,更多相關(guān)JS發(fā)起HTTP請求內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在B/S開發(fā)中經(jīng)常用到的JavaScript技術(shù)
javascript運用中,經(jīng)常用到的代碼,建議每段代碼都要看下,注意本文有三頁,仔細看玩,逐個研究透徹,那么網(wǎng)頁中常見的問題,你也就熟悉掌握了2008-05-05Javascript new關(guān)鍵字的玄機 以及其它
本人是Javascript菜鳥,下面是前幾天學習Javascript的旅程心得,希望對和我一樣的入門者有點用,也希望高手批評指正。2010-08-08JavaScript操作XML/HTML比較常用的對象屬性集錦
本文給大家介紹javascript操作xml/html比較常用的對象屬性,涉及到js對象屬性相關(guān)知識,對JavaScript操作XML/HTML比較常用的對象屬性感興趣的朋友可以參考下本文2015-10-10