js中的原生網(wǎng)絡(luò)請(qǐng)求解讀
早在很多年前,我們發(fā)送網(wǎng)絡(luò)請(qǐng)求都是通過刷新或者跳轉(zhuǎn)頁(yè)面來獲取新的網(wǎng)絡(luò)數(shù)據(jù),從而達(dá)到渲染不同頁(yè)面的需求,用戶體驗(yàn)是很差的,直到 ajax 橫空出生,才解決了這個(gè)問題,不需要刷新頁(yè)面便可以獲取請(qǐng)求數(shù)據(jù),這也是后來前后端分離的重要根源,大大的提高了網(wǎng)頁(yè)性能,優(yōu)化了用戶體驗(yàn)。
而 ajax 的核心就是我們今天要學(xué)的的原生請(qǐng)求,**XMLHttpRequest**對(duì)象。
一. XMLHttpRequer 對(duì)象
創(chuàng)建: 通過 new 來創(chuàng)建。
1. 使用 XHR
open
: 接收三個(gè)參數(shù),分別為請(qǐng)求類型,請(qǐng)求的URL,請(qǐng)求是否異步,該方法為發(fā)送請(qǐng)求做好準(zhǔn)備send
: 接收一個(gè)參數(shù),請(qǐng)求體發(fā)送的內(nèi)容,如果不發(fā)送,必須寫入null,該方法開始發(fā)送請(qǐng)求status
: 相應(yīng)的 HTTP 狀態(tài)碼,當(dāng)位于 200~300 或者 等于 304 時(shí),說明響應(yīng)成功返回。responseText
: 作為響應(yīng)體返回的文本statuesText
: 響應(yīng) HTTP 的狀態(tài)描述abort
: 該方法用來取消異步請(qǐng)求,會(huì)停止觸發(fā)事件,調(diào)用該方法后應(yīng)該取消對(duì)XHR對(duì)象的引用,不要重用XHR對(duì)象。onreadystatechange
: 用來監(jiān)聽請(qǐng)求位于哪個(gè)階段,該方法應(yīng)該在open前調(diào)用,該事件不會(huì)接收到event對(duì)象readyState
: 表示當(dāng)前請(qǐng)求位于哪個(gè)階段
0: 未初始化,尚未調(diào)用 open
1:已經(jīng)調(diào)用open,尚未調(diào)用 send
2:已經(jīng)送,已經(jīng)調(diào)用send,未收到響應(yīng)
3:接收中,已經(jīng)收到部分響應(yīng)
4:完成,接收到所有響應(yīng)
let xhr = new XMLHttpRequest(); // 創(chuàng)建XMLHttpRequest 實(shí)例 xhr.open("get", "http://127.0.0.1:3000/index", false); //設(shè)置為同步get請(qǐng)求 xhr.send(null); // 開始發(fā)送請(qǐng)求,并且阻塞后續(xù)代碼執(zhí)行,直到拿到響應(yīng) if((xhr.status >=200 && xhr.status <300) || xhr.status == 304){ ?? ?console.log(xhr.responseText) // 檢驗(yàn)狀態(tài)碼 }else{ ?? ?console.log('請(qǐng)求失敗') }
使用readyState:
每次該值的改變,都會(huì)觸發(fā)readystatechange 事件,因此我們可以在不同階段執(zhí)行不同操作
let xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ // 監(jiān)聽請(qǐng)求完成 ?? ?if((xhr.status >=200 && xhr.status <300) || xhr.status == 304){ ?? ??? ?console.log(xhr.responseText) ?? ?}else{ ?? ??? ?console.log('請(qǐng)求失敗') ?? ??? ?} ? ?? ?} } xhr.open("get", "http://127.0.0.1:3000/index", true); // 異步請(qǐng)求 xhr.send(null);
2. HTTP 頭部
① 默認(rèn)頭部信息
每個(gè)HTTP 請(qǐng)求和響應(yīng)都會(huì)攜帶頭部信息,我們來看一下默認(rèn)的一些請(qǐng)求頭部
Accept
: 瀏覽器可以處理的內(nèi)容類型Accept-Charset
:瀏覽器可以顯示的字符集Accept-Encoding
: 瀏覽器可以壓縮的編碼類型Connection
: 瀏覽器與服務(wù)的連接類型Cookie
:頁(yè)面中設(shè)置的CookieHost
: 發(fā)送請(qǐng)求頁(yè)面所在的域Referrer
:發(fā)送請(qǐng)求的頁(yè)面URLUser-Agent
: 瀏覽器的用戶代理字符串
②設(shè)置自定義頭部信息
setRequestHeader()
: 該方法接收兩個(gè)參數(shù),頭部字段的名稱和值,該方法必須在open之后,send 之前調(diào)用getResponseHeader()
: 從XHR對(duì)象獲取響應(yīng)頭部,只需要傳入獲取頭部的名稱即可getAllResponeHeaders()
: 獲取所有響應(yīng)頭信息
3. GET 請(qǐng)求
用于向服務(wù)器查詢某些信息,數(shù)據(jù)直接顯示在url中
① 傳參
需要將信息編碼后,添加到URL末尾,用 ? 隔開,各個(gè)參數(shù)用&隔開,參數(shù)的鍵值用=隔開
function addURLParam(url, name, value){ ?? ?const code = url.indexOf('?') == -1 ? '?' : '&'; ?? ?url += code; ?? ?url += (encodeURIComponent(name) + '=' + encodeURIComponent(value)) ?? ?return url; }
4. POST 請(qǐng)求
用于向服務(wù)器發(fā)送應(yīng)該保存的數(shù)據(jù),該數(shù)據(jù)在請(qǐng)求體中傳輸,只需要將要發(fā)送的數(shù)據(jù)寫入send方法中即可。
let btn = document.getElementById('btn') btn.onclick = function(){ ?? ?const xhr = new XMLHttpRequest(); ?? ?xhr.open('post', '/post', false); ?? ?xhr.send('sssss') }
5. XMLHttpRequest 標(biāo)準(zhǔn)2
① FormData 類型
用于將表單數(shù)據(jù)序列化,可以使用post請(qǐng)求模擬表單提交,使用該方法默認(rèn)將請(qǐng)求類型,設(shè)置為表單格式。
xhr.setRequestHeader('Content-Type', "application/x-www-form-urlencoded")
實(shí)例反法:
append: 接收兩個(gè)參數(shù),通過鍵值對(duì)的方式,將數(shù)據(jù)填入表單
let form = new FormData(); form.append('age','12') form.append('name', '石頭山')
也可以在構(gòu)造函數(shù)中傳入一個(gè)表單。
let form = new FormData(document.forms[0);
② 超時(shí)
用于表示發(fā)送請(qǐng)求后需要等待多少毫秒,如果響應(yīng)不成功就中斷請(qǐng)求
timeout: 用來設(shè)置超時(shí)時(shí)間,如果超時(shí)則會(huì)觸發(fā) ontimeout 事件,同時(shí) readyState 的狀態(tài)也會(huì)變成 4,同時(shí)調(diào)用 onreadystatechange 事件,并且超時(shí)之后訪問 statues 屬性會(huì)出錯(cuò)
切記,同步請(qǐng)求不能設(shè)置超時(shí)
xhr.open('post', '/post', true); // 此處只能為 true? xhr.timeout = 1000; xhr.ontimeout = function(){ ?? ?console.log('請(qǐng)求超時(shí)') ?? ?} xhr.send(null)
二. 進(jìn)度事件
loadstart
: 在接收到響應(yīng)的第一個(gè)字節(jié)時(shí)觸發(fā)progress
: 在接收響應(yīng)期間反復(fù)觸發(fā)error
:在請(qǐng)求出錯(cuò)時(shí)觸發(fā)abort
:在調(diào)用 abort()終止連接時(shí)觸發(fā)load
: 在成功接收完響應(yīng)時(shí)觸發(fā)loadend
:在通信完成時(shí),在error,abort,load之后觸發(fā)
1. load事件
該屬性用來題代 readystatechange 事件,但是有一個(gè)問題,只有從服務(wù)器收到響應(yīng),無(wú)論狀態(tài)碼是什么,都會(huì)觸發(fā)該事件,因此還需要檢驗(yàn)狀態(tài)碼來確保數(shù)據(jù)有效。
? ? ? ? ? ? const xhr = new XMLHttpRequest(); ? ? ? ? ? ? xhr.open('get', '/index', true); ? ? ? ? ? ? xhr.onload = function(){ ? ? ? ? ? ? ? ? if((xhr.status >= 200 && xhr.status<300) || xhr.status === 304){ ? ? ? ? ? ? ? ? ? ? console.log(xhr.responseText,'ss11'); ? ? ? ? ? ? ? ? }else{ ? ? ? ? ? ? ? ? ? ? console.log('請(qǐng)求錯(cuò)誤') ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? ? ? xhr.send(null)
2. progress 事件
在數(shù)據(jù)接收期間,該事件反復(fù)觸發(fā),該事件對(duì)象有三個(gè)屬性
lengthComputable
: 表示進(jìn)度信息是否可用position
:接收到的字節(jié)數(shù)totalSize
: 是響應(yīng)體頭部 Content-Length 的總字節(jié)數(shù)
? ? ? ? ? ? xhr.onprogress = function(event) { ? ? ? ? ? ? ? ? if(event.lengthComputable){ ? ? ? ? ? ? ? ? ? ? console.log(event.total, event.position) ? ? ? ? ? ? ? ? } ? ? ? ? ? ? }
三. 跨資源共享
1. 跨域安全策略
默認(rèn)情況XHR只能訪問與發(fā)起請(qǐng)求的頁(yè)面在同一個(gè)域內(nèi)的資源。
- 原生跨域:給open傳入一個(gè)絕對(duì)路徑則跨源訪問
- 限制:
1.不能是使用setRequestHeader() 設(shè)置自定義頭部
2.不能發(fā)送和接收cookie
3.getAllResponseHeaders() 方法始終返回 空字符串
因此,在訪問本地資源時(shí)使用相對(duì)路徑,訪問遠(yuǎn)程資源時(shí)使用絕對(duì)路徑
2. 預(yù)檢請(qǐng)求
通過該機(jī)制,允許使用自定義頭部,除GET和POST外的方法,在發(fā)送請(qǐng)求時(shí)先發(fā)送一個(gè)預(yù)檢請(qǐng)求,這個(gè)請(qǐng)求使用OPTIONS方法發(fā)送以下頭部。
Origin
:與簡(jiǎn)單請(qǐng)求相同Access-Control-Request-Method
: 請(qǐng)求希望使用的方法Access-Control-Request-Headers
: 自定義頭部列表
服務(wù)器可以確定是否允許這種類型的請(qǐng)求。會(huì)在響應(yīng)中發(fā)送如下頭部
Access-Control-Allow-Origin
: 允許的同源Access-Control-Allow-Methods
: 允許的方法Access-Control-Allow-Headers
: 允許的自定義頭部Access-Control-Allow-Max-Age
: 緩存預(yù)檢請(qǐng)求的秒數(shù)
預(yù)檢請(qǐng)求返回后,會(huì)緩存一段時(shí)間,在這段時(shí)間內(nèi)再次訪問不需要預(yù)檢。
3. 憑據(jù)請(qǐng)求
默認(rèn)情況下,跨源請(qǐng)求不提供憑據(jù),cookie,http認(rèn)證,SSl證書。可以通過將withCredentials 屬性設(shè)置為true來表明請(qǐng)求會(huì)發(fā)送憑證。
如果服務(wù)器允許攜帶,則在響應(yīng)頭部添加
Access-Control-Allow-Credentials: true.
四. 替代性跨源技術(shù)
1. 圖片探測(cè)
2. JSONP
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
javascript禁止訪客復(fù)制網(wǎng)頁(yè)內(nèi)容的實(shí)現(xiàn)代碼
這篇文章主要介紹了javascript禁止訪客復(fù)制網(wǎng)頁(yè)內(nèi)容的方法,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08Javascript實(shí)現(xiàn)基本運(yùn)算器
這篇文章主要為大家詳細(xì)介紹了Javascript實(shí)現(xiàn)基本運(yùn)算器的相關(guān)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07使用JavaScript的ActiveXObject對(duì)象檢測(cè)應(yīng)用程序是否安裝的方法
這篇文章主要介紹了使用JavaScript的ActiveXObject對(duì)象檢測(cè)應(yīng)用程序是否安裝的方法,需要的朋友可以參考下2014-04-04微信小程序?qū)崿F(xiàn)slideUp、slideDown滑動(dòng)效果及點(diǎn)擊空白隱藏功能示例
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)slideUp、slideDown滑動(dòng)效果及點(diǎn)擊空白隱藏功能,涉及微信小程序事件響應(yīng)、頁(yè)面元素屬性動(dòng)態(tài)操作實(shí)現(xiàn)滑動(dòng)與蒙層功能相關(guān)技巧與注意事項(xiàng),需要的朋友可以參考下2018-12-12微信小程序創(chuàng)建自定義全局函數(shù)以及其調(diào)用方法詳解
微信小程序有時(shí)需要函數(shù)里面調(diào)用函數(shù),下面這篇文章主要給大家介紹了關(guān)于微信小程序創(chuàng)建自定義全局函數(shù)以及其調(diào)用方法的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09javascript中數(shù)組的sort()方法的使用介紹
數(shù)組的sort()方法用于排序,在本文將為大家介紹下javascript中sort()方法的具體使用2013-12-12