JS發(fā)起HTTP請(qǐng)求的多種方式總結(jié)
為了更好的理解HTTP協(xié)議先來(lái)了解一下IP和TCP協(xié)議。
- IP(Internet Protocol)協(xié)議和TCP(Transmission Control Protocol)協(xié)議是互聯(lián)網(wǎng)的基礎(chǔ)協(xié)議,它們位于網(wǎng)絡(luò)協(xié)議棧的較低層次,主要負(fù)責(zé)數(shù)據(jù)包的發(fā)送和接收。
- IP協(xié)議是網(wǎng)絡(luò)層的協(xié)議,主要負(fù)責(zé)將數(shù)據(jù)包發(fā)送到正確的設(shè)備。每個(gè)連接到互聯(lián)網(wǎng)的設(shè)備都有一個(gè)唯一的IP地址,IP協(xié)議就是通過(guò)這個(gè)地址將數(shù)據(jù)包發(fā)送到正確的設(shè)備。
- TCP協(xié)議是傳輸層的協(xié)議,主要負(fù)責(zé)在兩個(gè)設(shè)備之間建立可靠的連接,并保證數(shù)據(jù)包的順序和完整性。TCP協(xié)議會(huì)對(duì)數(shù)據(jù)包進(jìn)行編號(hào),確保接收端能夠按照正確的順序接收數(shù)據(jù)包,如果有數(shù)據(jù)包丟失,TCP協(xié)議還會(huì)要求發(fā)送端重新發(fā)送。
HTTP(HyperText Transfer Protocol)協(xié)議則位于應(yīng)用層,它是建立在TCP協(xié)議之上的。HTTP協(xié)議定義了客戶端和服務(wù)器之間如何進(jìn)行數(shù)據(jù)交換,例如請(qǐng)求的格式、響應(yīng)的格式等。當(dāng)在瀏覽器中輸入一個(gè)網(wǎng)址時(shí),瀏覽器就會(huì)通過(guò)HTTP協(xié)議向服務(wù)器發(fā)送請(qǐng)求,并接收服務(wù)器的響應(yīng)。
所以,HTTP協(xié)議依賴于TCP協(xié)議來(lái)傳輸數(shù)據(jù),而TCP協(xié)議又依賴于IP協(xié)議來(lái)將數(shù)據(jù)包發(fā)送到正確的設(shè)備。
筆者屬于前端開發(fā),接下來(lái)的一段時(shí)間要總結(jié)在前端開發(fā)領(lǐng)域處于戰(zhàn)略地位的知識(shí)點(diǎn)。HTTP請(qǐng)求就屬于前端戰(zhàn)略知識(shí)點(diǎn)之一。
本文來(lái)總結(jié)下發(fā)起HTTP的幾種方式。
使用 XMLHttpRequest
XMLHttpRequest是比較底層也比較早期的發(fā)起http請(qǐng)求的方式,XMLHttpRequest不是基于Promise的所以往往在使用XMLHttpRequest時(shí)需要手動(dòng)封裝為Promise形式。
export const ajax = function (config) {
return new Promise((resolve, reject) => {
// 2. 發(fā)起XHR請(qǐng)求,默認(rèn)請(qǐng)求方法為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實(shí)際是對(duì)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)絡(luò)請(qǐng)求接口,它也提供了一種跨網(wǎng)絡(luò)異步獲取資源。Fetch基于Promise設(shè)計(jì)。主要特點(diǎn)
- 基于Promise:返回的Promise對(duì)象,可以使用then方法進(jìn)行鏈?zhǔn)秸{(diào)用,使得異步代碼更易于管理。
- 靈活性:Fetch可以自定義請(qǐng)求的各種設(shè)置,如請(qǐng)求方法(GET、POST等)、請(qǐng)求頭、請(qǐng)求體等。
- 支持跨域請(qǐng)求:Fetch支持CORS(跨源資源共享),可以進(jìn)行跨域請(qǐng)求。
- 支持流處理: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客戶端和服務(wù)端都屬于HTTP協(xié)議的設(shè)備。瀏覽器又通過(guò)HTTP協(xié)議與服務(wù)器發(fā)生交互,自然瀏覽器本身也具有發(fā)起HTTP請(qǐng)求的功能。
排除XMLHttpRequest、Fetch。瀏覽器自身還可以通過(guò)地址欄、通過(guò)html的相關(guān)標(biāo)簽發(fā)起HTTP請(qǐng)求。
html標(biāo)簽img、script、link、a、video、audio等都可以通過(guò)src或者h(yuǎn)ref屬性發(fā)情HTTP請(qǐng)求,當(dāng)然只能發(fā)起get請(qǐng)求。
還有html的form標(biāo)簽,可以發(fā)起get和post請(qǐng)求。
使用cURL
cURL是一個(gè)命令行工具,它允許通過(guò)各種協(xié)議向服務(wù)器發(fā)送請(qǐng)求并接收響應(yīng)。支持的協(xié)議非常多,包括 HTTP、HTTPS、FTP、FTPS、SFTP、SCP、LDAP、LDAPS、SMTP、POP3、IMAP、RTSP、RTMP、TELNET、TFTP等。
主要特點(diǎn)包括
- 支持多協(xié)議:如上所述,cURL 支持非常多的協(xié)議,可以滿足各種網(wǎng)絡(luò)請(qǐng)求的需求。
- 支持?jǐn)?shù)據(jù)上傳和下載:cURL 可以用于文件的上傳和下載,非常適合進(jìn)行批量操作。
- 支持 SSL 證書:cURL 支持 SSL 證書,可以進(jìn)行安全的網(wǎng)絡(luò)請(qǐng)求。
- 支持代理:cURL 支持通過(guò)代理服務(wù)器進(jìn)行網(wǎng)絡(luò)請(qǐng)求。
- 支持用戶認(rèn)證:cURL 支持各種用戶認(rèn)證方式,如基本認(rèn)證、摘要認(rèn)證、NTLM 認(rèn)證等。
使用 cURL 發(fā)起一個(gè) GET 請(qǐng)求
curl https://api.example.com/data
后端與后端之間
后端與后端之間也可以發(fā)起請(qǐng)求。這里java的HttpClient來(lái)發(fā)起HTTP的get請(qǐng)求
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)建了一個(gè)HttpClient對(duì)象,然后創(chuàng)建一個(gè)HttpRequest對(duì)象,指定了請(qǐng)求的URL。然后使用 HttpClient的send方法發(fā)送請(qǐng)求,并獲取到HttpResponse對(duì)象。
nginx中轉(zhuǎn)
nginx是比較知名的HTTP請(qǐng)求中間件。雖然不能直接發(fā)起HTTP,但可以作為代理,將請(qǐng)求做轉(zhuǎn)發(fā)。
一個(gè)簡(jiǎn)單的Nginx配置示例,用于解決跨域問(wèn)題
server {
listen 80;
server_name localhost;
location /api/ {
proxy_pass http://backend_server; # 這里是實(shí)際服務(wù)器的地址
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
上面設(shè)置了一個(gè)反向代理,將所有以 /api/ 開頭的請(qǐng)求轉(zhuǎn)發(fā)給 http://backend_server。這樣,前端就可以通過(guò)訪問(wèn) http://localhost/api/ 來(lái)進(jìn)行數(shù)據(jù)交互,而不會(huì)產(chǎn)生跨域問(wèn)題。
小程序發(fā)起
微信小程序提供了wx.request來(lái)發(fā)起HTTP請(qǐng)求
wx.request({
url: 'https://api.example.com/data', // 請(qǐng)求的 URL
method: 'GET', // 請(qǐng)求方法
data: { // 請(qǐng)求參數(shù)
key: 'value'
},
header: { // 設(shè)置請(qǐng)求的 header
'content-type': 'application/json'
},
success(res) { // 請(qǐng)求成功的回調(diào)函數(shù)
console.log(res.data)
},
fail(err) { // 請(qǐng)求失敗的回調(diào)函數(shù)
console.error(err)
}
})
注意的是,由于微信小程序的安全策略,開發(fā)者需要在微信公眾平臺(tái)配置服務(wù)器域名,只有配置過(guò)的域名才能被微信小程序請(qǐng)求。此外,微信小程序不支持跨域請(qǐng)求,也不支持使用 Cookie。
android發(fā)起
在Android開發(fā)中,可以使用多種方式來(lái)發(fā)起HTTP請(qǐng)求,其中最常用的是使用OkHttp庫(kù)
// 創(chuàng)建 OkHttpClient
OkHttpClient client = new OkHttpClient();
// 創(chuàng)建 Request
Request request = new Request.Builder()
.url("http://example.com")
.build();
// 使用 OkHttpClient 發(fā)起請(qǐng)求
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)絡(luò)請(qǐng)求是在后臺(tái)線程中進(jìn)行的,所以不能直接在回調(diào)函數(shù)中更新UI。需要使用 runOnUiThread方法來(lái)在主線程中更新UI。
此外,由于Android不允許在主線程中進(jìn)行網(wǎng)絡(luò)請(qǐng)求,所以這段代碼需要在后臺(tái)線程中運(yùn)行。
Websocket
WebSocket的握手過(guò)程使用的是HTTP協(xié)議,但一旦握手成功,服務(wù)器與客戶端之間的交互就完全依賴于WebSocket協(xié)議了。所以嚴(yán)格來(lái)說(shuō)Websocket不算HTTP請(qǐng)求。
WebSocket協(xié)議支持全雙工通信,即服務(wù)器和客戶端可以同時(shí)發(fā)送接收信息,而HTTP協(xié)議是半雙工的,即任一時(shí)刻要么是請(qǐng)求要么是響應(yīng),不能同時(shí)進(jìn)行。
一個(gè)簡(jiǎn)單的在瀏覽器中使用WebSocket的例子
// 創(chuàng)建 WebSocket 連接
var socket = new WebSocket('ws://localhost:8080');
// 連接打開時(shí)觸發(fā)
socket.onopen = function(event) {
console.log('WebSocket is connected.');
// 發(fā)送一個(gè)初始化消息
socket.send('Hello, Server!');
};
// 接收到消息時(shí)觸發(fā)
socket.onmessage = function(event) {
console.log('Received: ' + event.data);
// 關(guān)閉連接
socket.close();
};
// 連接關(guān)閉時(shí)觸發(fā)
socket.onclose = function(event) {
console.log('WebSocket is closed.');
};
// 連接發(fā)生錯(cuò)誤時(shí)觸發(fā)
socket.onerror = function(error) {
console.log('WebSocket Error: ' + error);
};
到此這篇關(guān)于JS發(fā)起HTTP請(qǐng)求的多種方式總結(jié)的文章就介紹到這了,更多相關(guān)JS發(fā)起HTTP請(qǐng)求內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一個(gè)不錯(cuò)的應(yīng)用,用于提交獲取文章內(nèi)容,不推薦用
一個(gè)不錯(cuò)的應(yīng)用,用于提交獲取文章內(nèi)容,不推薦用...2007-03-03
分享一個(gè)自己寫的簡(jiǎn)單的javascript分頁(yè)組件
這篇文章主要分享一個(gè)自己寫的簡(jiǎn)單的javascript分頁(yè)組件,效果十分不錯(cuò),代碼也很詳盡,這里推薦給小伙伴們。2015-02-02
js語(yǔ)法學(xué)習(xí)之判斷一個(gè)對(duì)象是否為數(shù)組
這篇文章主要介紹了從javascript判斷一個(gè)對(duì)象是否為數(shù)組中學(xué)習(xí)js語(yǔ)法,需要的朋友可以參考下2014-05-05
在B/S開發(fā)中經(jīng)常用到的JavaScript技術(shù)
javascript運(yùn)用中,經(jīng)常用到的代碼,建議每段代碼都要看下,注意本文有三頁(yè),仔細(xì)看玩,逐個(gè)研究透徹,那么網(wǎng)頁(yè)中常見的問(wèn)題,你也就熟悉掌握了2008-05-05
微信小程序多文件上傳 Tdesign及導(dǎo)入失敗問(wèn)題
小程序文件上傳還是有點(diǎn)麻煩的,其實(shí)主要還是小程序?qū)Φ慕涌谟兄T多的不便,比如說(shuō),文件不能批量提交,只能一個(gè)個(gè)的提交,小程序的上傳需要專門的接口,這篇文章主要介紹了微信小程序多文件上傳 Tdesign及導(dǎo)入失敗問(wèn)題,需要的朋友可以參考下2023-11-11
JS中的Replace方法使用經(jīng)驗(yàn)分享
本文給大家分享的是我們?cè)谑褂胘avascript中的replace方法的時(shí)候需要注意的一個(gè)事項(xiàng),我就是沒有注意到,才被這個(gè)bug煩了好久,這里記錄下來(lái),有需要的小伙伴可以參考下。2015-05-05
Javascript new關(guān)鍵字的玄機(jī) 以及其它
本人是Javascript菜鳥,下面是前幾天學(xué)習(xí)Javascript的旅程心得,希望對(duì)和我一樣的入門者有點(diǎn)用,也希望高手批評(píng)指正。2010-08-08
JavaScript操作XML/HTML比較常用的對(duì)象屬性集錦
本文給大家介紹javascript操作xml/html比較常用的對(duì)象屬性,涉及到j(luò)s對(duì)象屬性相關(guān)知識(shí),對(duì)JavaScript操作XML/HTML比較常用的對(duì)象屬性感興趣的朋友可以參考下本文2015-10-10

