XMLHttpRequest實(shí)現(xiàn)HTTP通信的示例詳解
由于 QML 的 JavaScript 兼容性,我們可以直接使用 JavaScript 的 XMLHttpRequest 對象進(jìn)行 HTTP 請求。QML 的 XMLHttpRequest 實(shí)現(xiàn)與標(biāo)準(zhǔn)瀏覽器的實(shí)現(xiàn)非常相似,但有一些限制和特殊行為需要注意。
而QML實(shí)現(xiàn)TCP等其他通信一般就需要借助Qt與C++的關(guān)系了,本文對此略過
1. XMLHttpRequest對象詳解
1.1 屬性
readyState:當(dāng)前對象的狀態(tài)碼,取值如下:0(UNSENT):未初始化,尚未調(diào)用open()。1(OPENED):已調(diào)用open(),但未調(diào)用send()。2(HEADERS_RECEIVED):已接收響應(yīng)頭。3(LOADING):正在接收響應(yīng)體。4(DONE):請求完成,響應(yīng)數(shù)據(jù)就緒。
status:int,當(dāng)前HTTP請求的狀態(tài)碼(如200成功,404未找到,見3.3)。statusText:string,HTTP響應(yīng)的狀態(tài)文本(如 “OK”、“Not Found” 等,見3.3)。只有在readyState為DONE時(shí)才有效。responseType:string,響應(yīng)內(nèi)容的數(shù)據(jù)類型。responseText:string,服務(wù)器的響應(yīng)數(shù)據(jù),以純文本形式表示。僅在responseType為text或未設(shè)置時(shí)有效response:var,根據(jù)responseType解析后的響應(yīng)數(shù)據(jù)(如 JSON 對象、二進(jìn)制數(shù)據(jù))。默認(rèn)為""(空字符串),在 QML 中可以通過設(shè)置responseType來獲取不同類型的數(shù)據(jù)。responseURL:string,Qt6.6引入,實(shí)際響應(yīng)的URL,如果請求被重定向,則返回最終的 URL。responseXML:var,服務(wù)器的響應(yīng)數(shù)據(jù),以XML文檔形式表示,僅當(dāng)響應(yīng)內(nèi)容為XML格式時(shí)有效。timeout:int,超時(shí)時(shí)間(以毫秒為單位)。如果設(shè)置,當(dāng)請求超過指定時(shí)間仍未完成時(shí)會觸發(fā)ontimeout事件。withCredentials:bool,表示是否在跨域請求中發(fā)送憑據(jù)(如 Cookies)。僅在支持 CORS 的服務(wù)器上有效。
1.2 方法
void open(method, url, async):初始化請求。method:HTTP 方法(如 GET、POST、PUT)。url:請求地址(支持相對路徑和絕對路徑)。async:是否異步(可省略,默認(rèn)為true,QML中通常不推薦設(shè)為false)。
void send(data):發(fā)送請求。data:獲取的請求體內(nèi)容(GET 請求可省略或傳null,POST 可傳FormData或 JSON 字符串)。
void setRequestHeader(header, value):設(shè)置請求頭(需在open()之后、send()之前調(diào)用)。void abort():終止當(dāng)前請求。string getAllResponseHeaders():string getResponseHeader(headerName):
1.3 事件
onreadystatechange:function,函數(shù)類型,每當(dāng)readyState在幾個(gè)狀態(tài)中發(fā)生變化時(shí)就會觸發(fā),執(zhí)行函數(shù),用于監(jiān)聽請求狀態(tài)。一般為其指定函數(shù),用于指定處理各種狀態(tài)變化后的事件。onerror:function,函數(shù)類型,網(wǎng)絡(luò)錯(cuò)誤時(shí)觸發(fā)(如域名解析失?。瑘?zhí)行函數(shù)。ontimeout:function,函數(shù)類型,請求超時(shí)時(shí)觸發(fā)(需先設(shè)置timeout屬性),執(zhí)行函數(shù)。onload:function,函數(shù)類型,請求成功完成時(shí)觸發(fā)(readyState === DONE且status === 200),執(zhí)行函數(shù)。onprogress:function,函數(shù)類型,上傳或下載進(jìn)度更新時(shí)觸發(fā)(適用于大文件傳輸),執(zhí)行函數(shù)。
2. XMLHttpRequest對象的使用
總示例如下:
function postCMD(cmd){
httpRequest("http://127.0.0.1:7111/track/" + cmd, "POST", null, function(resultS, status){
if(status === 200){
}else{
/// \todo warning message
}
})
}
function httpRequest(serverUrl, method, data, callback){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (xhr.readyState === XMLHttpRequest.HEADERS_RECEIVED){
}else if(xhr.readyState === XMLHttpRequest.DONE){
if(callback){
callback(xhr.responseText.toString() ,xhr.status)
}
}
}
xhr.open(method, serverUrl);
xhr.timeout = 3000;
xhr.setRequestHeader("Connection", "close");
if(!data){
xhr.send();
}else{
xhr.send(data);
}
}
2.1 使用XMLHttpRequest的流程
創(chuàng)建 XMLHttpRequest 對象。
調(diào)用 open() 配置請求。
設(shè)置請求頭。(可選)
設(shè)置 responseType。(可選)
監(jiān)聽 onreadystatechange,處理響應(yīng)。(在發(fā)送請求之前配置即可即可)
調(diào)用 void send(data) 方法發(fā)送請求并傳送數(shù)據(jù)。
2.2 配置請求的基本信息和請求頭
- 使用
new創(chuàng)建對象 - 使用
void open(method, url, async)初始化請求,指定HTTP方法和請求地址。 - 使用
void setRequestHeader(header, value)指定請求頭的key和value,可累積配置。 - 還可以指定一些其他參數(shù),如通過設(shè)置
timeout屬性來設(shè)置時(shí)間限制等等。
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://127.0.0.1:12345/");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Authorization", "Bearer your_token_here");
xhr.timeout = 3000;
2.3 監(jiān)聽事件狀態(tài)進(jìn)行對應(yīng)處理
在需要的時(shí)候?yàn)槭录x值函數(shù),類似于回調(diào)函數(shù),讓在對應(yīng)狀態(tài)發(fā)生變化的時(shí)候觸發(fā)此函數(shù)來獲得想要的結(jié)果。
一般都會對readyState的onreadystatechange事件進(jìn)行監(jiān)聽,以對請求的狀態(tài)有著整體的把握。并且能在請求結(jié)束的時(shí)候,通過responseText等屬性獲取GET的數(shù)據(jù)等。
xhr.onreadystatechange = function() {
console.log("當(dāng)前 readyState:", xhr.readyState);
if (xhr.readyState === XMLHttpRequest.DONE) { // 請求完成
if (xhr.status === 200) { // 成功響應(yīng)
console.log("請求成功!");
console.log("響應(yīng)數(shù)據(jù):", xhr.responseText);
} else {
console.error("請求失敗,狀態(tài)碼:", xhr.status);
}
}
}
xhr.onerror = function() {
console.error("網(wǎng)絡(luò)錯(cuò)誤: 無法連接到服務(wù)器");
}
// 對于ontimeout、onload、onprogress都是同理
2.4 發(fā)送請求
在配置完成后使用void send(data)方法發(fā)送請求并傳送數(shù)據(jù)。
對于參數(shù)data,如果是 GET 請求可省略或傳 null,而如果是 POST 可傳 FormData 或 JSON 字符串。
// GET時(shí)候可用 xhr.send(); // 通用 var data = ''; data = "...."; // 數(shù)據(jù) xhr.send(data);
3. 進(jìn)階用法
3.1 發(fā)送 FormData(表單數(shù)據(jù))
適用于文件上傳或 multipart/form-data 格式:
function uploadFile() {
var xhr = new XMLHttpRequest();
var formData = new FormData();
formData.append("file", fileInput.files[0]); // 假設(shè) fileInput 是文件選擇框
formData.append("comment", "QML 文件上傳測試");
xhr.open("POST", "https://api.example.com/upload");
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
console.log("上傳結(jié)果:", xhr.status);
}
};
xhr.send(formData);
}
3.2 處理二進(jìn)制數(shù)據(jù)(如圖片)
通過設(shè)置 responseType 為 "arraybuffer",可直接獲取二進(jìn)制數(shù)據(jù):
function loadImage() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://example.com/image.png");
xhr.responseType = "arraybuffer";
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
var byteArray = new Uint8Array(xhr.response);
var imageData = "data:image/png;base64," + btoa(String.fromCharCode.apply(null, byteArray));
imageElement.source = imageData; // 顯示圖片
}
};
xhr.send();
}
3.3 常見請求的狀態(tài)碼
| 狀態(tài)碼 | 含義 | 典型場景 |
|---|---|---|
| 200 | 請求成功 | 常規(guī) GET/POST 請求 |
| 201 | 資源已創(chuàng)建 | 創(chuàng)建新用戶、提交表單 |
| 204 | 請求成功,但無內(nèi)容 | DELETE 請求 |
| 301 | 資源永久移動 | URL 重寫 |
| 302 | 資源臨時(shí)移動 | 登錄后跳轉(zhuǎn) |
| 304 | 資源未修改,使用緩存 | 條件請求 |
| 400 | 請求無效 | 表單數(shù)據(jù)錯(cuò)誤 |
| 401 | 未授權(quán) | 需要登錄 |
| 403 | 禁止訪問 | 權(quán)限不足 |
| 404 | 資源不存在 | 頁面或 API 路徑錯(cuò)誤 |
| 405 | 方法不被允許 | 不支持的 HTTP 方法 |
| 429 | 請求過多 | 觸發(fā)速率限制 |
| 500 | 服務(wù)器內(nèi)部錯(cuò)誤 | 代碼崩潰或數(shù)據(jù)庫問題 |
| 502 | 網(wǎng)關(guān)錯(cuò)誤 | 上游服務(wù)不可用 |
| 503 | 服務(wù)不可用 | 服務(wù)器維護(hù)或過載 |
| 504 | 網(wǎng)關(guān)超時(shí) | 上游服務(wù)響應(yīng)超時(shí) |
3.4 跨域請求與 withCredentials
跨域請求是常見的需求,特別是在需要攜帶 Cookies 或認(rèn)證信息時(shí)。通過設(shè)置 withCredentials 屬性為 true,可以在跨域請求中發(fā)送憑據(jù)。
要注意的是,服務(wù)器必須支持 CORS(跨域資源共享),并允許 credentials,如果服務(wù)器未正確配置 CORS,可能會導(dǎo)致請求失敗。
function makeCORSRequest() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/data", true);
xhr.withCredentials = true; // 允許跨域請求攜帶憑據(jù)
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
console.log("跨域請求成功:", xhr.responseText);
} else {
console.error("跨域請求失敗,狀態(tài)碼:", xhr.status);
}
}
};
xhr.send();
}
3.5 利用onprogress事件監(jiān)控上傳/下載進(jìn)度
對于大文件下載,可以通過 onprogress 事件實(shí)時(shí)更新下載進(jìn)度,并顯示給用戶。
function downloadFile(url) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onprogress = function(event) {
if (event.lengthComputable) {
var percentComplete = (event.loaded / event.total) * 100;
console.log("下載進(jìn)度:", percentComplete.toFixed(2) + "%");
} else {
console.log("無法計(jì)算總大小,正在下載...");
}
};
xhr.onload = function() {
if (xhr.status === 200) {
console.log("文件下載完成!");
} else {
console.error("下載失敗,狀態(tài)碼:", xhr.status);
}
};
xhr.onerror = function() {
console.error("網(wǎng)絡(luò)錯(cuò)誤: 無法連接到服務(wù)器");
};
xhr.send();
}
類似地,對于大文件上傳,也可以通過 onprogress 事件監(jiān)控上傳進(jìn)度。
function uploadFile(fileInput) {
var xhr = new XMLHttpRequest();
var formData = new FormData();
formData.append("file", fileInput.files[0]);
xhr.open("POST", "https://api.example.com/upload", true);
xhr.upload.onprogress = function(event) {
if (event.lengthComputable) {
var percentComplete = (event.loaded / event.total) * 100;
console.log("上傳進(jìn)度:", percentComplete.toFixed(2) + "%");
} else {
console.log("無法計(jì)算總大小,正在上傳...");
}
};
xhr.onload = function() {
if (xhr.status === 200) {
console.log("文件上傳成功!");
} else {
console.error("上傳失敗,狀態(tài)碼:", xhr.status);
}
};
xhr.onerror = function() {
console.error("網(wǎng)絡(luò)錯(cuò)誤: 無法連接到服務(wù)器");
};
xhr.send(formData);
}
到此這篇關(guān)于XMLHttpRequest實(shí)現(xiàn)HTTP通信的示例詳解的文章就介紹到這了,更多相關(guān)XMLHttpRequest HTTP通信內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js合并數(shù)組對象代碼實(shí)現(xiàn)(將數(shù)組中具有相同屬性對象合并到一起組成一個(gè)新數(shù)組)
項(xiàng)目過程中經(jīng)常會遇到JS數(shù)組合并的情況,時(shí)常為這個(gè)糾結(jié),這篇文章主要給大家介紹了關(guān)于js合并數(shù)組對象(將數(shù)組中具有相同屬性對象合并到一起組成一個(gè)新數(shù)組)的相關(guān)資料,需要的朋友可以參考下2024-01-01
JavaScript實(shí)現(xiàn)頁面高亮操作提示和蒙板
這篇文章主要介紹了JavaScript實(shí)現(xiàn)頁面高亮操作提示和蒙板,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-01-01
利用Three.js制作一個(gè)新聞聯(lián)播開頭動畫
這篇文章主要為大家介紹了如何利用Three.js制作一個(gè)新聞聯(lián)播開頭動畫,文中的實(shí)現(xiàn)步驟講解詳細(xì),對我們學(xué)習(xí)有一定幫助,需要的可以參考一下2022-05-05
一些Javascript的IE和Firefox(火狐)兼容性的問題總結(jié)及常用例子
下面是一些Javascript的IE和Firefox(火狐)兼容性的常用例子2009-05-05
uniapp頁面間傳參的幾種方法實(shí)例總結(jié)
在進(jìn)行頁面的跳轉(zhuǎn)的時(shí)候,往往需要我們將一些參數(shù)攜帶著傳遞過去,下面這篇文章主要給大家介紹了關(guān)于uniapp頁面間傳參的幾種方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-12-12
Jquery+javascript實(shí)現(xiàn)支付網(wǎng)頁數(shù)字鍵盤
這篇文章主要為大家詳細(xì)介紹了Jquery+javascript實(shí)現(xiàn)支付網(wǎng)頁數(shù)字鍵盤,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12

