javascript
网络编程-JavaScript中发送网络请求汇总
文章目錄
- 1.前后端分離優(yōu)勢(shì)
- 2.HTTP協(xié)議的解析
- 2.1 HTTP的介紹
- 2.2 HTTP的組成
- 2.3 HTTP的版本
- 2.4 HTTP請(qǐng)求方式
- 2.5 HTTP請(qǐng)求頭字段
- 2.6 HTTP響應(yīng)狀態(tài)碼
- 2.7 HTTP響應(yīng)頭
- 3.AJAX網(wǎng)絡(luò)請(qǐng)求
- 3.1 AJAX發(fā)送請(qǐng)求
- 3.2 XHR的狀態(tài)
- 3.3 XHR其他事件監(jiān)聽
- 3.4 響應(yīng)數(shù)據(jù)和響應(yīng)類型
- 3.5 HTTP的響應(yīng)狀態(tài)
- 3.7 GET/POST傳遞參數(shù)
- 4.AJAX網(wǎng)絡(luò)請(qǐng)求封裝
- 補(bǔ)充: 過期時(shí)間和取消請(qǐng)求
- 過期時(shí)間
- 取消請(qǐng)求
- 5.Fetch使用和上傳文件
- 5.1 Fetch基本使用
- 5.2 Fetch數(shù)據(jù)的響應(yīng)
- 5.3 Fetch網(wǎng)絡(luò)請(qǐng)求的演練
- 5.4 Fetch POST請(qǐng)求
- 5.4 Fetch POST請(qǐng)求
1.前后端分離優(yōu)勢(shì)
早期的網(wǎng)頁都是通過后端渲染來完成的:服務(wù)器端渲染(SSR,server side render):
- 客戶端發(fā)出請(qǐng)求 -> 服務(wù)端接收請(qǐng)求并返回相應(yīng)HTML文檔 -> 頁面刷新,客戶端加載新的HTML文檔;
服務(wù)器端渲染的缺點(diǎn):
- 當(dāng)用戶點(diǎn)擊頁面中的某個(gè)按鈕向服務(wù)器發(fā)送請(qǐng)求時(shí),頁面本質(zhì)上只是一些數(shù)據(jù)發(fā)生了變化,而此時(shí)服務(wù)器卻要將重繪的整個(gè)頁面再返回給瀏覽器加載,這顯然有悖于程序員的“DRY( Don‘t repeat yourself )”原則;
- 而且明明只是一些數(shù)據(jù)的變化卻迫使服務(wù)器要返回整個(gè)HTML文檔,這本身也會(huì)給網(wǎng)絡(luò)帶寬帶來不必要的開銷。
有沒有辦法在頁面數(shù)據(jù)變動(dòng)時(shí),只向服務(wù)器請(qǐng)求新的數(shù)據(jù),并且在阻止頁面刷新的情況下,動(dòng)態(tài)的替換頁面中展示的數(shù)據(jù)呢?
- 答案正是“AJAX”。
AJAX是“Asynchronous JavaScript And XML”的縮寫(異步的JavaScript和XML),是一種實(shí)現(xiàn)無頁面刷新獲取服務(wù)器數(shù)據(jù)的技術(shù)。
- AJAX最吸引人的就是它的“異步”特性,也就是說它可以在不重新刷新頁面的情況下與服務(wù)器通信,交換數(shù)據(jù),或更新頁面。
你可以使用AJAX最主要的兩個(gè)特性做下列事 :
- 在不重新加載頁面的情況下發(fā)送請(qǐng)求給服務(wù)器;
- 接受并使用從服務(wù)器發(fā)來的數(shù)據(jù)。
這里有兩幅圖給大家理解一下:
2.HTTP協(xié)議的解析
2.1 HTTP的介紹
什么是HTTP呢?我們來看一下維基百科的解釋:
- 超文本傳輸協(xié)議(英語:HyperText Transfer Protocol,縮寫:HTTP)是一種用于分布式、協(xié)作式和超媒體信息系統(tǒng)的應(yīng)用層協(xié)議;
- HTTP是萬維網(wǎng)的數(shù)據(jù)通信的基礎(chǔ),設(shè)計(jì)HTTP最初的目的是為了提供一種發(fā)布和接收HTML頁面的方法;
- 通過HTTP或者HTTPS協(xié)議請(qǐng)求的資源由統(tǒng)一資源標(biāo)識(shí)符(Uniform Resource Identifiers,URI)來標(biāo)識(shí);
HTTP是一個(gè)客戶端(用戶)和服務(wù)端(網(wǎng)站)之間請(qǐng)求和響應(yīng)的標(biāo)準(zhǔn)。
通過使用網(wǎng)頁瀏覽器、網(wǎng)絡(luò)爬蟲或者其它的工具,客戶端發(fā)起一個(gè)HTTP請(qǐng)求到服務(wù)器上指定端口(默認(rèn)端口為80);
- 我們稱這個(gè)客戶端為用戶代理程序(user agent);
響應(yīng)的服務(wù)器上存儲(chǔ)著一些資源,比如HTML文件和圖像。
- 我們也稱這個(gè)響應(yīng)服務(wù)器為源服務(wù)器(origin server);
我們網(wǎng)頁中的資源通常是被放在Web資源服務(wù)器中,由瀏覽器自動(dòng)發(fā)送HTTP請(qǐng)求來獲取、解析、展示的。
目前我們頁面中很多數(shù)據(jù)是動(dòng)態(tài)展示的:
- 比如頁面中的數(shù)據(jù)展示、搜索數(shù)據(jù)、表單驗(yàn)證等等,也是通過在JavaScript中發(fā)送HTTP請(qǐng)求獲取的;
2.2 HTTP的組成
一次HTTP請(qǐng)求主要包括:請(qǐng)求(Request)和響應(yīng)(Response)(如下圖所示)
請(qǐng)求又包含請(qǐng)求行、請(qǐng)求頭、請(qǐng)求體 (如下圖所示)
響應(yīng)也包含響應(yīng)行、響應(yīng)頭、響應(yīng)體 (如下圖所示)
2.3 HTTP的版本
HTTP/0.9
- 發(fā)布于1991年;
- 只支持GET請(qǐng)求方法獲取文本數(shù)據(jù),當(dāng)時(shí)主要是為了獲取HTML頁面內(nèi)容;
HTTP/1.0
- 發(fā)布于1996年;
- 支持POST、HEAD等請(qǐng)求方法,支持請(qǐng)求頭、響應(yīng)頭等,支持更多種數(shù)據(jù)類型(不再局限于文本數(shù)據(jù)) ;
- 但是瀏覽器的每次請(qǐng)求都需要與服務(wù)器建立一個(gè)TCP連接,請(qǐng)求處理完成后立即斷開TCP連接,每次建立連接增加了性能損耗;
HTTP/1.1(目前使用最廣泛的版本)
- 發(fā)布于1997年;
- 增加了PUT、DELETE等請(qǐng)求方法;
- 采用持久連接(Connection: keep-alive),多個(gè)請(qǐng)求可以共用同一個(gè)TCP連接;
HTTP/2.0, 2015年
HTTP/3.0, 2018年
2.4 HTTP請(qǐng)求方式
在RFC中定義了一組請(qǐng)求方式,來表示要對(duì)給定資源執(zhí)行的操作:
-
GET:GET 方法請(qǐng)求一個(gè)指定資源的表示形式,使用 GET 的請(qǐng)求應(yīng)該只被用于獲取數(shù)據(jù)。
-
HEAD:HEAD 方法請(qǐng)求一個(gè)與 GET 請(qǐng)求的響應(yīng)相同的響應(yīng),但沒有響應(yīng)體。
比如在準(zhǔn)備下載一個(gè)文件前,先獲取文件的大小,再?zèng)Q定是否進(jìn)行下載;
-
POST:POST 方法用于將實(shí)體提交到指定的資源。
-
PUT:PUT 方法用請(qǐng)求有效載荷(payload)替換目標(biāo)資源的所有當(dāng)前表示;
-
DELETE:DELETE 方法刪除指定的資源;
-
PATCH:PATCH 方法用于對(duì)資源應(yīng)部分修改;
-
CONNECT:CONNECT 方法建立一個(gè)到目標(biāo)資源標(biāo)識(shí)的服務(wù)器的隧道,通常用在代理服務(wù)器,網(wǎng)頁開發(fā)很少用到。
-
TRACE:TRACE 方法沿著到目標(biāo)資源的路徑執(zhí)行一個(gè)消息環(huán)回測(cè)試。
在開發(fā)中使用最多的是GET、POST請(qǐng)求;
- 在后續(xù)的后臺(tái)管理項(xiàng)目中,我們也會(huì)使用PATCH、DELETE請(qǐng)求;
2.5 HTTP請(qǐng)求頭字段
在request對(duì)象的header中也包含很多有用的信息,客戶端會(huì)默認(rèn)傳遞過來一些信息(如下) :
content-type: 這次請(qǐng)求攜帶的數(shù)據(jù)的類型
- application/x-www-form-urlencoded:表示數(shù)據(jù)被編碼成以 ‘&’ 分隔的鍵 - 值對(duì),同時(shí)以 ‘=’ 分隔鍵和值
- application/json:表示是一個(gè)json類型;
- text/plain:表示是文本類型;
- application/xml:表示是xml類型;
- multipart/form-data:表示是上傳文件;
content-length:文件的大小長(zhǎng)度
keep-alive :
- http是基于TCP協(xié)議的,但是通常在進(jìn)行一次請(qǐng)求和響應(yīng)結(jié)束后會(huì)立刻中斷;
- 在http1.0中,如果想要繼續(xù)保持連接:
- 瀏覽器需要在請(qǐng)求頭中添加 connection: keep-alive;
- 服務(wù)器需要在響應(yīng)頭中添加 connection:keey-alive;
- 當(dāng)客戶端再次放請(qǐng)求時(shí),就會(huì)使用同一個(gè)連接,直接一方中斷連接;
- 在http1.1中,所有連接默認(rèn)是 connection: keep-alive的;
- 不同的Web服務(wù)器會(huì)有不同的保持 keep-alive的時(shí)間;
- Node中默認(rèn)是5s中;
accept-encoding:告知服務(wù)器,客戶端支持的文件壓縮格式,比如js文件可以使用gzip編碼,對(duì)應(yīng) .gz文件;
accept:告知服務(wù)器,客戶端可接受文件的格式類型;
user-agent:客戶端相關(guān)的信息;
2.6 HTTP響應(yīng)狀態(tài)碼
Http狀態(tài)碼(Http Status Code)是用來表示Http響應(yīng)狀態(tài)的數(shù)字代碼:
- Http狀態(tài)碼非常多,可以根據(jù)不同的情況,給客戶端返回不同的狀態(tài)碼;
| 200 | OK | 客戶端請(qǐng)求成功 |
| 201 | Created | POST請(qǐng)求,創(chuàng)建新的資源 |
| 301 | Moved Permanently | 請(qǐng)求資源的URL已經(jīng)修改,響應(yīng)中會(huì)給出新的URL |
| 400 | Bad Request | 客戶端的錯(cuò)誤,服務(wù)器無法或者不進(jìn)行處理 |
| 401 | Unauthorized | 未授權(quán)的錯(cuò)誤,必須攜帶請(qǐng)求的身份信息 |
| 403 | Forbidden | 客戶端沒有權(quán)限訪問,被拒接 |
| 404 | Not Found | 服務(wù)器找不到請(qǐng)求的資源。 |
| 500 | Internal Server Error | 服務(wù)器遇到了不知道如何處理的情況。 |
| 503 | Service Unavailable | 服務(wù)器不可用,可能處理維護(hù)或者重載狀態(tài),暫時(shí)無法訪問 |
更多響應(yīng)碼介紹在MDN文檔上, 鏈接給到大家: MDN上響應(yīng)碼文檔: https://developer.mozilla.org/zh-CN/docs/web/http/status
2.7 HTTP響應(yīng)頭
響應(yīng)的header中包括一些服務(wù)器給客戶端的信息:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-L3n6aQgp-1657070357626)(img/Snipaste_2022-07-05_11-06-57.png)]
3.AJAX網(wǎng)絡(luò)請(qǐng)求
3.1 AJAX發(fā)送請(qǐng)求
AJAX 是異步的 JavaScript 和 XML(Asynchronous JavaScript And XML)
- 它可以使用 JSON,XML,HTML 和 text 文本等格式發(fā)送和接收數(shù)據(jù);
如何來完成AJAX請(qǐng)求呢?
-
第一步:創(chuàng)建網(wǎng)絡(luò)請(qǐng)求的AJAX對(duì)象(使用XMLHttpRequest)
-
第二步:監(jiān)聽XMLHttpRequest對(duì)象狀態(tài)的變化,或者監(jiān)聽onload事件(請(qǐng)求完成時(shí)觸發(fā));
-
第三步:配置網(wǎng)絡(luò)請(qǐng)求(通過open方法), open方法可以傳入兩個(gè)參數(shù);
參數(shù)一: method(請(qǐng)求的方式: get, post …)
參數(shù)二: url(請(qǐng)求的地址)
-
第四步:發(fā)送send網(wǎng)絡(luò)請(qǐng)求;
【演示代碼】
// 1.創(chuàng)建網(wǎng)絡(luò)請(qǐng)求對(duì)象 const xhr = new XMLHttpRequest()// 2.監(jiān)聽對(duì)象狀態(tài)的變化 xhr.addEventListener("readystatechange", function() {// 拿到網(wǎng)絡(luò)請(qǐng)求的結(jié)果console.log(xhr.response) })// 3.配置網(wǎng)絡(luò)請(qǐng)求 // 參數(shù)一: 請(qǐng)求的方式; 參數(shù)二: 要請(qǐng)求的url地址 xhr.open("get", "http://192.168.0.110:1888")// 4.發(fā)生網(wǎng)絡(luò)請(qǐng)求 xhr.send()發(fā)送同步請(qǐng)求:
-
我們發(fā)送網(wǎng)絡(luò)請(qǐng)求, 默認(rèn)是異步的, 但是我們也可以發(fā)送同步的網(wǎng)絡(luò)請(qǐng)求
-
我們是需要將open的第三個(gè)參數(shù)設(shè)置為false (默認(rèn)時(shí)true), 就可以開啟同步的請(qǐng)求
-
當(dāng)然我們實(shí)際開發(fā)還是用異步的請(qǐng)求
3.2 XHR的狀態(tài)
事實(shí)上,我們?cè)谝淮尉W(wǎng)絡(luò)請(qǐng)求中看到狀態(tài)發(fā)生了很多次變化,這是因?yàn)閷?duì)于一次請(qǐng)求來說包括如下的狀態(tài):
| 0 | UNSENT | 代理被創(chuàng)建,但尚未調(diào)用 open() 方法。 |
| 1 | OPENED | open() 方法已經(jīng)被調(diào)用。 |
| 2 | HEADERS_RECEIVED | send() 方法已經(jīng)被調(diào)用,并且頭部和狀態(tài)已經(jīng)可獲得。 |
| 3 | LOADING | 下載中;responseText 屬性已經(jīng)包含部分?jǐn)?shù)據(jù)。 |
| 4 | DONE | 下載操作已完成。 |
狀態(tài)0我們是監(jiān)聽不到的
例如: 我們想要獲取結(jié)果, 應(yīng)該在下載操作已完成后獲取
// 1.創(chuàng)建網(wǎng)絡(luò)請(qǐng)求對(duì)象 const xhr = new XMLHttpRequest()// 2.監(jiān)聽對(duì)象狀態(tài)的變化 xhr.addEventListener("readystatechange", function() {// 狀態(tài)不為4的話直接returnif (xhr.readyState !== XMLHttpRequest.DONE) return// 拿到的結(jié)果是一個(gè)字符串, 我們可以轉(zhuǎn)成js對(duì)象const resJSON = JSON.parse(xhr.response)console.log(resJSON) })// 3.配置網(wǎng)絡(luò)請(qǐng)求 // 參數(shù)一: 請(qǐng)求的方式; 參數(shù)二: 要請(qǐng)求的url地址 xhr.open("get", "http://192.168.0.110:1888")// 4.發(fā)生網(wǎng)絡(luò)請(qǐng)求 xhr.send()注意<:這個(gè)狀態(tài)并非是HTTP的響應(yīng)狀態(tài),而是記錄的XMLHttpRequest對(duì)象的狀態(tài)變化。
- http響應(yīng)狀態(tài)通過status獲取;
3.3 XHR其他事件監(jiān)聽
我們除了可以監(jiān)聽readystatechange之外, 還有其他的事件可以監(jiān)聽
- loadstart:請(qǐng)求開始。
- progress: 一個(gè)響應(yīng)數(shù)據(jù)包到達(dá),此時(shí)整個(gè) response body 都在 response 中。
- abort:調(diào)用 xhr.abort() 取消了請(qǐng)求。
- error:發(fā)生連接錯(cuò)誤,例如,域錯(cuò)誤。不會(huì)發(fā)生諸如 404 這類的 HTTP 錯(cuò)誤。
- load:請(qǐng)求成功完成。
- timeout:由于請(qǐng)求超時(shí)而取消了該請(qǐng)求(僅發(fā)生在設(shè)置了 timeout 的情況下)。
- loadend:在 load,error,timeout 或 abort 之后觸發(fā)。
我們也可以在load中獲取請(qǐng)求數(shù)據(jù):
// 在load中獲取請(qǐng)求結(jié)果 xhr.addEventListener("load", function() {console.log(xhr.response) })3.4 響應(yīng)數(shù)據(jù)和響應(yīng)類型
發(fā)送了請(qǐng)求后,我們需要獲取對(duì)應(yīng)的結(jié)果:response屬性
- XMLHttpRequest response 屬性返回響應(yīng)的正文內(nèi)容;
- 返回的類型取決于responseType的屬性設(shè)置
通過responseType可以設(shè)置獲取數(shù)據(jù)的類型
- 如果將 responseType 的值設(shè)置為空字符串,則會(huì)使用 text 作為默認(rèn)值。
- 設(shè)置數(shù)據(jù)類型, 一般在監(jiān)聽事件之后, 且在send方法之前
和responseText、responseXML的區(qū)別:
- 早期通常服務(wù)器返回的數(shù)據(jù)是普通的文本和XML,所以我們通常會(huì)通過responseText、 responseXML來獲取響應(yīng)結(jié)果 , 之后將它們轉(zhuǎn)化成JavaScript對(duì)象形式;
- 目前服務(wù)器基本返回的都是json數(shù)據(jù),直接設(shè)置為json即可;
3.5 HTTP的響應(yīng)狀態(tài)
前面我們提到, XMLHttpRequest的state是用于記錄xhr對(duì)象本身的狀態(tài)變化,并非針對(duì)于HTTP的網(wǎng)絡(luò)請(qǐng)求狀態(tài)。
如果我們希望獲取HTTP響應(yīng)的網(wǎng)絡(luò)狀態(tài),可以通過status和statusText來獲取:
- status是獲取狀態(tài)碼
- statusText是獲取狀態(tài)描述
我們寫一個(gè)不存在的接口, 測(cè)試一下狀態(tài)碼和狀態(tài)描述
const xhr = new XMLHttpRequest()xhr.addEventListener("load", function() {console.log(xhr.response) // null// 1.獲取狀態(tài)碼console.log(xhr.status) // 404// 2.獲取狀態(tài)描述console.log(xhr.statusText) // Not Found })xhr.responseType = "json"xhr.open("get", "http://123.207.32.32:8000/aaa/bbb/ccc")xhr.send()大家可以再看看剛剛的常用狀態(tài)碼表格
| 200 | OK | 客戶端請(qǐng)求成功 |
| 201 | Created | POST請(qǐng)求,創(chuàng)建新的資源 |
| 301 | Moved Permanently | 請(qǐng)求資源的URL已經(jīng)修改,響應(yīng)中會(huì)給出新的URL |
| 400 | Bad Request | 客戶端的錯(cuò)誤,服務(wù)器無法或者不進(jìn)行處理 |
| 401 | Unauthorized | 未授權(quán)的錯(cuò)誤,必須攜帶請(qǐng)求的身份信息 |
| 403 | Forbidden | 客戶端沒有權(quán)限訪問,被拒接 |
| 404 | Not Found | 服務(wù)器找不到請(qǐng)求的資源。 |
| 500 | Internal Server Error | 服務(wù)器遇到了不知道如何處理的情況。 |
| 503 | Service Unavailable | 服務(wù)器不可用,可能處理維護(hù)或者重載狀態(tài),暫時(shí)無法訪問 |
3.7 GET/POST傳遞參數(shù)
在開發(fā)中,我們使用最多的是GET和POST請(qǐng)求,在發(fā)送請(qǐng)求的過程中,我們也可以傳遞給服務(wù)器數(shù)據(jù)。
常見的傳遞給服務(wù)器數(shù)據(jù)的方式有如下幾種 :
-
方式一:GET請(qǐng)求的query參數(shù)(常用)
const xhr = new XMLHttpRequest()xhr.addEventListener("load", function() {// 傳入的參數(shù)服務(wù)器會(huì)返回console.log(xhr.response) })xhr.responseType = "json"// 在傳入的url輸入查詢字符串傳遞參數(shù) xhr.open("get", "http://123.207.32.32:1888/02_param/get?name=kaisa&age=18&address=成都市" )xhr.send()請(qǐng)求結(jié)果
-
方式二:POST請(qǐng)求 x-www-form-urlencoded 格式
const xhr = new XMLHttpRequest()xhr.addEventListener("load", function() {console.log(xhr.response) })xhr.responseType = "json"// 1.發(fā)送post請(qǐng)求 xhr.open("post", "http://123.207.32.32:1888/02_param/posturl")// 2.告知服務(wù)器要發(fā)送數(shù)據(jù)的格式 xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded") // 3.在請(qǐng)求體中傳入?yún)?shù) xhr.send("name=kaisa&age=18&address=成都市")請(qǐng)求結(jié)果
-
方式三:POST請(qǐng)求 FormData 格式
-
方式四:POST請(qǐng)求 JSON 格式(常用)
const xhr = new XMLHttpRequest()xhr.addEventListener("load", function() {console.log(xhr.response) })xhr.responseType = "json"// 1.發(fā)送post請(qǐng)求 xhr.open("post", "http://123.207.32.32:1888/02_param/posturl")// 2.告知服務(wù)器要發(fā)送數(shù)據(jù)的格式 xhr.setRequestHeader("Content-type", "application/json")// 3.發(fā)送JSON格式的字符串 xhr.send(JSON.stringify({ name: "kaisa", age: 18, height: 1.88 }))請(qǐng)求結(jié)果
4.AJAX網(wǎng)絡(luò)請(qǐng)求封裝
在實(shí)際開發(fā)中, 我們并不會(huì)自己封裝AJAX, 而是直接使用axios庫, 再對(duì)axios庫進(jìn)行二次封裝
我們封裝AJAX原因是借此練習(xí)一下前面所學(xué)的知識(shí)
由于我們每次使用網(wǎng)絡(luò)請(qǐng)求, 都寫寫很多行同樣的代碼, 使用起來是非常不方便的, 我們封裝的目的就是為了使用起來更方便
封裝步驟的解釋寫在代碼注釋里面, 源代碼和測(cè)試代碼給大家
// 定義一個(gè)函數(shù)封裝ajax, // 由于使用參數(shù)可能會(huì)傳很多個(gè), 因此我們可以讓使用者傳入一個(gè)對(duì)象 function myajax({url,method = "get",date = {},success,failure } = {}) {// 1.創(chuàng)建對(duì)象const xhr = new XMLHttpRequest()// 2.監(jiān)聽數(shù)據(jù)xhr.onload = function() {// 用響應(yīng)碼判斷是否成功if (xhr.status >= 200 && xhr.status < 300) {success && success(xhr.response)} else {failure && failure({ status: xhr.status, message: xhr.statusText })}}// 3.設(shè)置響應(yīng)類型xhr.responseType = "json"// 考慮get請(qǐng)求放在date對(duì)象中的情況單獨(dú)處理if (method.toUpperCase() === "GET") {const urlStrings = []for (key in date) {urlStrings.push(`${key}=${date[key]}`)}url = url + "?" + urlStrings.join("&")xhr.open(method, url)xhr.send()} else {// 4.open方法xhr.open(method, url)// 5.send方法xhr.setRequestHeader("Content-type", "application/json")xhr.send(JSON.stringify(date))} }// 測(cè)試get請(qǐng)求 myajax({url: "http://123.207.32.32:1888/02_param/get",date: {name: "get",age: 18},// 傳入一個(gè)請(qǐng)求成功的回調(diào)success: function(res) {console.log(res)},// 傳入失敗的回調(diào)failure: function(err) {console.log("err", err)} })// 測(cè)試post請(qǐng)求 myajax({url: "http://123.207.32.32:1888/02_param/posturl",method: "post",// 傳入一個(gè)請(qǐng)求成功的回調(diào)success: function(res) {console.log(res)},date: {name: "post",age: 18},// 傳入失敗的回調(diào)failure: function(err) {console.log("err", err)} })我們對(duì)上面的基本封裝做一點(diǎn)優(yōu)化, 為了防止回調(diào)地獄的情況出現(xiàn), 我們可以返回一個(gè)promise, 并且不需要再傳入成功的回調(diào)和失敗的回調(diào), 因?yàn)閜romise中有
function myajax({url,method = "get",date = {} } = {}) {// 返回一個(gè)promisereturn new Promise((resolve, reject) => {const xhr = new XMLHttpRequest() xhr.onload = function() {if (xhr.status >= 200 && xhr.status < 300) {// 使用resolve成功的回調(diào)resolve(xhr.response)} else {// 使用reject失敗的回調(diào)reject({ status: xhr.status, message: xhr.statusText })}} xhr.responseType = "json" if (method.toUpperCase() === "GET") {const urlStrings = []for (key in date) {urlStrings.push(`${key}=${date[key]}`)}url = url + "?" + urlStrings.join("&") xhr.open(method, url)xhr.send()} else {xhr.open(method, url) xhr.setRequestHeader("Content-type", "application/json")xhr.send(JSON.stringify(date))}}) }// 測(cè)試get請(qǐng)求 myajax({url: "http://123.207.32.32:1888/02_param/get",date: {name: "get",age: 18} // then中成功的結(jié)果 }).then(res => {console.log(res) // catch中失敗的結(jié)果 }).catch(err => {console.log(err) })// 測(cè)試post請(qǐng)求 myajax({url: "http://123.207.32.32:1888/02_param/posturl",method: "post",date: {name: "post",age: 18} // then中成功的結(jié)果 }).then(res => {console.log(res) // catch中失敗的結(jié)果 }).catch(err => {console.log(err) })補(bǔ)充: 過期時(shí)間和取消請(qǐng)求
下面我用的是一個(gè)延時(shí)的接口
過期時(shí)間
在網(wǎng)絡(luò)請(qǐng)求的過程中,為了避免過長(zhǎng)的時(shí)間服務(wù)器無法返回?cái)?shù)據(jù),通常我們會(huì)為請(qǐng)求設(shè)置一個(gè)超時(shí)時(shí)間:timeout。
- 當(dāng)達(dá)到超時(shí)時(shí)間后依然沒有獲取到數(shù)據(jù),那么這個(gè)請(qǐng)求會(huì)自動(dòng)被取消掉;
- 默認(rèn)值為0,表示沒有設(shè)置超時(shí)時(shí)間;
下面寫個(gè)案例, 如果超過3000毫秒沒有請(qǐng)求到數(shù)據(jù)就取消本次網(wǎng)絡(luò)請(qǐng)求
- 請(qǐng)求超時(shí)可以在timeout中監(jiān)聽
取消請(qǐng)求
取消網(wǎng)絡(luò)請(qǐng)求, 我們也可以通過abort方法強(qiáng)制 (手動(dòng)) 取消請(qǐng)求;
- 請(qǐng)求取消可以在abort中監(jiān)聽
5.Fetch使用和上傳文件
5.1 Fetch基本使用
Fetch可以看做是早期的XMLHttpRequest的替代方案,它提供了一種更加現(xiàn)代的處理方案:
比如返回值是一個(gè)Promise,提供了一種更加優(yōu)雅的處理結(jié)果方式
- 在請(qǐng)求發(fā)送成功時(shí),調(diào)用resolve回調(diào)then;
- 在請(qǐng)求發(fā)送失敗時(shí),調(diào)用reject回調(diào)catch;
比如不像XMLHttpRequest一樣,所有的操作都在一個(gè)對(duì)象上
fetch函數(shù)的使用:
fetch(input[, init])
input:定義要獲取的資源地址,可以是一個(gè)URL字符串,也可以使用一個(gè)Request對(duì)象(實(shí)驗(yàn)性特性)類型;
init:其他初始化參數(shù), 是一個(gè)對(duì)象
- method: 請(qǐng)求使用的方法,如 GET、POST;
- headers: 請(qǐng)求的頭信息;
- body: 請(qǐng)求的 body 信息;
【演示代碼】
發(fā)送一個(gè)get請(qǐng)求(先了解一下 馬上會(huì)詳細(xì)分析)
fetch("http://123.207.32.32:8000/home/multidata").then(res => {// 獲取具體的結(jié)果還需調(diào)用一次// 如果是文本就res.text, 其他的同樣的道理res.json().then(res => {console.log(res)}) }).catch(err => {console.log(err) })5.2 Fetch數(shù)據(jù)的響應(yīng)
Fetch的數(shù)據(jù)響應(yīng)主要分為兩個(gè)階段 :
階段一:當(dāng)服務(wù)器返回了響應(yīng)(response)
- fetch 返回的 promise 就使用內(nèi)建的 Response class 對(duì)象來對(duì)響應(yīng)頭進(jìn)行解析;
- 在這個(gè)階段,我們可以通過檢查響應(yīng)頭,來檢查 HTTP 狀態(tài)以確定請(qǐng)求是否成功;
- 如果 fetch 無法建立一個(gè) HTTP 請(qǐng)求,例如網(wǎng)絡(luò)問題,亦或是請(qǐng)求的網(wǎng)址不存在,那么 promise 就會(huì) reject;
- 異常的 HTTP 狀態(tài),例如 404 或 500,不會(huì)導(dǎo)致出現(xiàn) error;
我們可以在 response 的屬性中看到 HTTP 狀態(tài):
- status:HTTP 狀態(tài)碼,例如 200;
- ok:布爾值,如果 HTTP 狀態(tài)碼為 200-299,則為 true;
第二階段,為了獲取 response body,我們需要使用一個(gè)其他的方法調(diào)用, 這個(gè)方法同樣返回Promise。
- response.text() —— 讀取 response,并以文本形式返回 response;
- response.json() —— 將 response 解析為 JSON;
5.3 Fetch網(wǎng)絡(luò)請(qǐng)求的演練
基于Promise的使用方案:
fetch("http://123.207.32.32:8000/home/multidata").then(res => {// 獲取具體的結(jié)果還需調(diào)用一次// 如果是文本就res.text, 其他的同樣的道理return res.json() }).then(res => {console.log(res) }).catch(err => {console.log(err) })基于async、await的使用方案:
async function getDate() {const response1 = await fetch("http://123.207.32.32:8000/home/multidata")const response2 = await response1.json()// 打印結(jié)果console.log(response2) }getDate()5.4 Fetch POST請(qǐng)求
創(chuàng)建一個(gè) POST 請(qǐng)求,或者其他方法的請(qǐng)求,我們需要使用 fetch 選項(xiàng):
method:HTTP 方法,例如 POST,
body:request body,其中之一:
- 字符串(例如 JSON 編碼的),
- FormData 對(duì)象,以 multipart/form-data 形式發(fā)送數(shù)據(jù),
5.4 Fetch POST請(qǐng)求
創(chuàng)建一個(gè) POST 請(qǐng)求,或者其他方法的請(qǐng)求,我們需要使用 fetch 選項(xiàng):
method:HTTP 方法,例如 POST,
body:request body,其中之一:
- 字符串(例如 JSON 編碼的),
- FormData 對(duì)象,以 multipart/form-data 形式發(fā)送數(shù)據(jù),
總結(jié)
以上是生活随笔為你收集整理的网络编程-JavaScript中发送网络请求汇总的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 若依集成actuator实现优雅关闭应用
- 下一篇: 让你认清楚JSP中的所有东西(java/