JavaScript >> Javascript 文檔 >  >> JavaScript

如何使用 XMLHttpRequest (XHR) 發出 HTTP 請求

XMLHttpRequest (XHR) 是微軟在 90 年代初發明的,並在 21 世紀頭十年中期成為異步服務器交互的首選技術。

多虧了 XHR,第一次可以在不重新加載整個頁面的情況下更新網頁的部分內容。

XMLHttpRequest 是所有現代瀏覽器中的內置瀏覽器對象,可用於在 JavaScript 中發出 HTTP 請求,以在 Web 瀏覽器和服務器之間交換數據。

儘管名稱中有“XML”一詞,但 XMLHttpRequest 可用於檢索任何類型的數據,而不僅僅是 XML。我們可以使用它來上傳/下載文件、提交表單數據、跟踪進度等等。

基本 XHR 請求

要使用 XHR 發送 HTTP 請求,請創建一個 XMLHttpRequest 對象,打開到 URL 的連接,然後發送請求。一旦請求完成,該對象將包含有用的信息,例如響應正文和 HTTP 狀態碼。

讓我們使用 JSONPlaceholder 測試 REST API 使用 XHR 發送 GET 請求:

// create an XHR object
const xhr = new XMLHttpRequest();

// listen for `onload` event
xhr.onload = () => {
    // process response
    if (xhr.status == 200) {
        // parse JSON data
        console.log(JSON.parse(xhr.response));
    } else {
        console.error('Error!');
    }
};

// create a `GET` request
xhr.open('GET', 'https://jsonplaceholder.typicode.com/users');

// send request
xhr.send();

xhr.open() 方法

在上面的示例中,我們將 HTTP 方法和請求的 URL 傳遞給 open() 方法。此方法通常在 new XMLHttpRequest() 之後立即調用 .我們可以使用這個方法來指定請求的主要參數:

下面是這個方法的語法:

xhr.open(method, URL, [async, user, password])
  • method — HTTP 請求方法。可以是GET , POST , DELETE , PUT 等。
  • URL — 要請求的 URL,字符串或 URL 對象
  • asnyc — 指定是否應異步發出請求。默認值為 true
  • username &password — 基本 HTTP 身份驗證的憑據

open() 方法不會打開到 URL 的連接。它只配置 HTTP 請求。

xhr.send() 方法

xhr.send([body])

send() 方法打開網絡連接並將請求發送到服務器。它需要一個可選的 body 包含請求正文的參數。對於像 GET 這樣的請求方法 不需要傳遞body參數。

XHR 事件

使用最廣泛的三個 XHR 事件如下:

  • load — 當結果準備好時調用此事件。相當於xhr.onreadystatechange xhr.readyState == 4 的事件 .
  • error — 由於網絡故障或無效 URL 導致請求失敗時觸發此事件。
  • progress — 此事件在響應下載期間定期觸發。它可用於報告大型網絡請求的進度。
// listen for `load` event
xhr.onload = () => {
    console.log(`Data Loaded: ${xhr.status} ${xhr.response}`);
};

// listen for `error` event
xhr.onerror = () => {
    console.error('Request failed.');
}

// listen for `progress` event
xhr.onprogress = (event) => {
    // event.loaded returns how many bytes are downloaded
    // event.total returns the total number of bytes
    // event.total is only available if server sends `Content-Length` header
    console.log(`Downloaded ${event.loaded} of ${event.total}`);
}

請求超時

您可以通過指定時間(以毫秒為單位)輕鬆配置請求超時:

// set timeout
xhr.timeout = 5000; // 5 seconds

// listen for `timeout` event
xhr.ontimeout = () => console.log('Request timeout.', xhr.responseURL);

響應類型

我們可以使用 xhr.responseType 設置預期響應格式的屬性:

  • 空(默認)或 text — 純文本
  • json — 解析的 JSON
  • blob — 二進制數據 Blob
  • document — XML 文檔
  • arraybufferArrayBuffer 對於二進制數據

讓我們調用一個 RESTful API 來獲取 JSON 格式的響應:

const xhr = new XMLHttpRequest();

xhr.open('GET', 'https://api.jsonbin.io/b/5d5076e01ec3937ed4d05eab/1');

// set response format
xhr.responseType = 'json';

xhr.send();

xhr.onload = () => {
    // get JSON response
    const user = xhr.response;

    // log details
    console.log(user.name); // John Doe
    console.log(user.email); // [email protected]
    console.log(user.website); // http://example.com
}

請求狀態(xhr.readyState )

XMLHttpRequest 對象隨著請求的進行而改變狀態。我們可以使用 xhr.readyState 訪問當前狀態 屬性。

狀態是:

  • UNSENT (0) — 初始狀態
  • OPENED (1) — 請求開始
  • HEADERS_RECEIVED (2) — 收到的 HTTP 標頭
  • LOADING (3) — 響應正在加載
  • DONE (4) — 請求完成

我們可以使用 onreadystatechange 來跟踪請求狀態 事件:

xhr.onreadystatechange = function () {
    if(xhr.readyState == 1) {
        console.log('Request started.');
    }
    
    if(xhr.readyState == 2) {
        console.log('Headers received.');
    }
    
    if (xhr.readyState == 3) {
        console.log('Data loading..!');
    }
    if (xhr.readyState == 4) {
        console.log('Request ended.');
    }
};

中止請求

我們可以隨時通過調用 abort() 輕鬆中止 XHR 請求 xhr 上的方法 對象:

xhr.abort(); // cancel request

同步請求

默認情況下,XHR 發出一個有利於性能的異步請求。但是如果你想發出一個顯式的同步請求,只需傳遞 false 作為 open() 的第三個參數 方法。它將在 send() 處暫停 JavaScript 執行 並在響應可用時恢復:

xhr.open('GET', 'https://api.jsonbin.io/b/5d5076e01ec3937ed4d05eab/1', false);

HTTP 標頭

XMLHttpRequest 允許我們設置請求標頭以及讀取響應標頭。我們可以設置請求Content-Type &Accept 通過調用 setRequestHeader() 標頭 xhr 上的方法 對象:

// set request headers
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Accept', '*/*'); // accept all

同樣,如果您想讀取響應標頭(Set-Cookie 除外) ),調用 getResponseHeader()xhr 對象:

// read response headers
xhr.getResponseHeader('Content-Type');
xhr.getResponseHeader('Cache-Control');

想要立即獲取響應標頭?使用 getAllResponseHeaders() 而是:

xhr.getAllResponseHeaders();

XHR POST 請求

XMLHttpRequest 提交表單數據的POST請求可以通過兩種方式發送:

  1. 僅使用 Ajax
  2. 使用 FormData API

第一種方法已經足夠好了,除非你想上傳一個文件並且需要 multipart/form-data 編碼。以下是我們如何使用 URL 編碼的表單數據發出 POST 請求:

const xhr = new XMLHttpRequest();

// configure a `POST` request
xhr.open('POST', '/login');

// prepare form data
let params = 'username=attacomsian&password=123456';

// set `Content-Type` header
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

// pass `params` to `send()` method
xhr.send(params);

// listen for `load` event
xhr.onload = () => {
   console.log(xhr.responseText);
}

想要發出 JSON POST 請求? 確保使用 JSON.stringify() 將 JSON 數據轉換為字符串並設置 Content-Type application/json 的標頭 :

const xhr = new XMLHttpRequest();

// configure a `POST` request
xhr.open('POST', '/login');

// create a JSON object
const params = {
    username: 'attacomsian',
    password: '123456'
};

// set `Content-Type` header
xhr.setRequestHeader('Content-Type', 'application/json');

// pass `params` to `send()` method
xhr.send(JSON.stringify(params));

// listen for `load` event
xhr.onload = () => {
   console.log(xhr.responseText);
}

跨域請求和 Cookies

XMLHttpRequest 可以發送跨域請求,但需要採取特殊的安全措施。要從不同的服務器請求資源,服務器必須使用 CORS(跨域資源共享)明確支持這一點。

就像 Fetch API 一樣,XHR 不會將 cookie 和 HTTP 授權發送到另一個來源。要發送 cookie,您可以使用 withCredentials xhr 的屬性 對象:

xhr.withCredentials = true;

XHR 與 jQuery

jQuery 包裝器方法,例如 $.ajax() 在底層使用 XHR 並提供更高級別的抽像以使開發人員的生活更輕鬆。使用 jQuery,我們可以將上面的代碼翻譯成幾行代碼:

$.ajax('https://jsonplaceholder.typicode.com/users')
    .done(data => {
        console.log(data);
    }).fail(err => {
        console.error('Error:', err);
    });

XHR 與 Fetch API

Fetch API 是基於 Promise 的現代 XHR 替代方案。它簡潔、易於理解,並在 PWA Service Worker 中大量使用。

上面的 XHR 示例可以轉換為更簡單的 fetch() - 甚至自動解析返回的 JSON 的代碼:

fetch('https://jsonplaceholder.typicode.com/users')
    .then(res => res.json())
    .then(json => console.log(json))
    .catch(err => console.error('Error:', err));

想要了解更多信息? 查看 JavaScript Fetch API 指南,了解如何通過幾行代碼使用 Fetch API 來請求網絡資源。


Tutorial JavaScript 教程
  1. 9 個適合初學者的有趣 Vue JS 項目創意,可以幫助你被錄用

  2. 基於項目的前端教程精選列表 [基於項目的學習前端]

  3. 簡單的蛇遊戲

  4. 為什麼以及如何開發 Design Sense? 👩🏽‍🎨

  5. Heroku 錯誤 /node_modules/node-sass:命令失敗

  6. 反應 useEffect Hook

  7. 使靜態 Web 應用 API 的身份驗證更簡單

  1. 重構之路

  2. 最好的現代 JavaScript  — 方法、IIFE 和這個

  3. 3 種有用的 JavaScript 泛型函數柯里化方法

  4. 10 個 jQuery DOM 插件

  5. 防止按 Enter 鍵提交表單 |示例代碼

  6. 構建一個沒有框架的 Javascript 單頁應用程序

  7. 如何使用 Javascript 創建可拖動列表 - 使用 Bishal 編寫代碼

  1. 以簡單的方式開始使用 TypeScript

  2. React 中的 JSX – 用示例解釋

  3. 如何使用基本 JavaScript 使您的待辦事項列表可編輯

  4. Firebase React 身份驗證教程