原生Ajax( XHR 和 Fetch )
原生Ajax 基本使用的四大步驟,簡單易懂
什么是ajax?
ajax(異步j(luò)avascript xml) 能夠刷新局部網(wǎng)頁數(shù)據(jù)而不是重新加載整個(gè)網(wǎng)頁。
如何使用ajax?
一般大家都把所用ajax分為4個(gè)步驟,但是我覺得應(yīng)該是3個(gè)步驟。(注意:ajax執(zhí)行步驟不等于執(zhí)行順序,官方都是把步驟三事件函數(shù)寫在步驟二的前面)
第一步: 創(chuàng)建 XMLHttpRequest 對象
var xmlhttp;
if (window.XMLHttpRequest)
{
// IE7+, Firefox, Chrome, Opera, Safari 瀏覽器執(zhí)行代碼
xmlhttp=new XMLHttpRequest();
}
else
{
// IE6, IE5 瀏覽器執(zhí)行代碼
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
第二步:向服務(wù)器發(fā)送請求請求
GET請求
xmlhttp.open("GET","/try/ajax/demo_get.php",true);
xmlhttp.send();
在上面的例子中,您可能得到的是緩存的結(jié)果。
為了避免這種情況,請向 URL 添加一個(gè)唯一的 ID:
xmlhttp.open("GET","/try/ajax/demo_get.php?t=" + Math.random(),true);
xmlhttp.send();
POST請求
xmlhttp.open("POST","/try/ajax/demo_post.php",true);
xmlhttp.send();
如果需要像 HTML 表單那樣 POST 數(shù)據(jù),請使用 setRequestHeader() 來添加 HTTP 頭。然后在 send() 方法中規(guī)定您希望發(fā)送的數(shù)據(jù):
xmlhttp.open("POST","/try/ajax/demo_post2.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("fname=Henry&lname=Ford");
第三步:onreadystatechange 事件
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
注:1、每當(dāng) readyState 改變時(shí),就會(huì)觸發(fā) onreadystatechange 事件。(readyState 屬性存有 XMLHttpRequest 的狀態(tài)信息)
2、實(shí)測 如果第三步的代碼在第二步之前則onreadystatechange 事件被觸發(fā) 4 次(0 - 4), 分別是: 0-1、1-2、2-3、3-4,對應(yīng)著 readyState 的變化;
如果第三步在第二步后面則onreadystatechange 事件被觸發(fā) 3 次(0 - 4), 分別是: 1-2、2-3、3-4,對應(yīng)著 readyState 的變化(這種情況的原因是當(dāng)readyState 從0-1變化時(shí),js從上到下執(zhí)行代碼時(shí),onreadystatechange 事件的執(zhí)行函數(shù)還沒定義,所以0-1的變化沒法觸發(fā)onreadystatechange 事件)。 【這應(yīng)該就是 http的 3次握手,4次揮手的過程】
3、一般認(rèn)為的第三步:
一般的資料中都把 服務(wù)器 響應(yīng) (獲得來自服務(wù)器的響應(yīng),使用 XMLHttpRequest 對象的 responseText 或 responseXML 屬性) 作為第三步,但是個(gè)人認(rèn)為這個(gè)不應(yīng)該作為開發(fā)的步驟,而是ajax對象返回的數(shù)據(jù)。
1、詳解Ajax請求(四)——多個(gè)異步請求的執(zhí)行順序 :(多個(gè)ajax回調(diào)函數(shù)執(zhí)行的順序不一定是從上到下的)
https://www.cnblogs.com/cdf-opensource-007/p/6371237.html
2、凡是 要 用到ajax返回?cái)?shù)據(jù)的代碼,必須在ajax的回調(diào)函數(shù)中執(zhí)行。因?yàn)閍jax是異步執(zhí)行的,當(dāng)ajax數(shù)據(jù) 還沒回來,其它的代碼都執(zhí)行了,這個(gè)時(shí)候外面的代碼用到這個(gè)數(shù)據(jù),就會(huì)報(bào)錯(cuò)。
3、ajax請求是異步的,發(fā)送請求后需要跳頁(重定向)的話(如:提交按鈕),跳轉(zhuǎn)頁面一定要放在ajax的回調(diào)函數(shù)里面,不然會(huì)導(dǎo)致ajax請求失敗。因?yàn)閍jax數(shù)據(jù)還沒返回來(ajax異步執(zhí)行,js進(jìn)程不管ajax怎么樣了,繼續(xù)執(zhí)行下面的代碼),js就執(zhí)行下面的跳頁,這個(gè)時(shí)候后臺(tái)數(shù)據(jù)返回來,無法傳遞到對應(yīng)的請求url中。雖然執(zhí)行了
window.location.href = "./**/*.html";語句,但是后面的代碼還是會(huì)繼續(xù)執(zhí)行的,ajax長時(shí)間沒有接受到返回的信息,就會(huì)執(zhí)行 error(jQuery庫)中的代碼。
注:至于window.location.href = "./**/*.html"; 已經(jīng)跳頁了,為什么后面代碼還會(huì)繼續(xù)執(zhí)行的問題,有時(shí)間在去了解。
4、location.href頁面跳轉(zhuǎn)后禁止后續(xù)操作 : http://baijiahao.baidu.com/s?id=1569994757645432&wfr=spider&for=pc
5、document.location和window.location有什么區(qū)別
參考:https://bbs.csdn.net/topics/330028654
(個(gè)人)一般情況都是一樣使用的,但是在iframe里面區(qū)別就出來了。
6、window.location.href = “ ”,這個(gè)重定向后面的代碼還是會(huì)執(zhí)行的。 (這個(gè)問題可以當(dāng)做js的一個(gè)bug,沒有必要深入了解,把這條語句放在最后面執(zhí)行就可以了。異步操作后執(zhí)行的就放在回調(diào)函數(shù)中執(zhí)行)
原因參考:https://www.zhihu.com/question/29890952?from=profile_question_card (沒有解釋清楚)
setTimeout(function(){
window.location.href = "./**/*.html";
alert("0");
alert("1");
alert("2");
},9000);
7、ajax請求中,無論后臺(tái)返回的什么類型的數(shù)據(jù),前端瀏覽器 返回的都是字符串類型(整體是string類型)。json格式化字符串轉(zhuǎn)換為對應(yīng)的對象(或 字符串類型 或 數(shù)值類型) 數(shù)據(jù)。
注意: '{ "name": "cxh", "sex": "man" }' 形式數(shù)據(jù)是json字符串; { "name": "cxh", "sex": "man" } 形式數(shù)據(jù)是json對象,不是字符串。
不管是json對象還是json字符串,它們的屬性名必須加雙引號。
后端返回的 { "name": "cxh", "sex": "man" } 類型數(shù)據(jù),就是json字符串,因?yàn)楹蠖朔祷氐臄?shù)據(jù)到前端后都是字符串類型。 參考鏈接
8、注意 ajax請求的url參數(shù)是可以相對路徑的:https://blog.csdn.net/hys1253731584/article/details/79503011
絕對路徑的url,也可以省略前面的域名端口的,看起來像相對路徑。即 ajax請求同源的 API 接口,絕對路徑也可以不寫 協(xié)議、域名、端口的。
9、ajax 請求,是獲取使用的數(shù)據(jù),有時(shí)是要判斷下(或try...catch),是否有數(shù)據(jù)(如獲取選手信息。調(diào)接口,發(fā)送選手id這個(gè)參數(shù),后臺(tái)查詢后,返回成功,但是數(shù)據(jù)為空),否則直接使用一個(gè)未定義對象 的方法或?qū)傩允菚?huì)報(bào)錯(cuò)的。
如果是有捕獲函數(shù)catch的話,則不會(huì)報(bào)錯(cuò),但會(huì)執(zhí)行catch內(nèi)的函數(shù),這不是想要的邏輯。
如: axios 請求中的catch函數(shù)(catch函數(shù)是在服務(wù)器報(bào)錯(cuò),才執(zhí)行的函數(shù)。服務(wù)器成功是200)。服務(wù)器返回200成功,但是因?yàn)閖s報(bào)錯(cuò)導(dǎo)致執(zhí)行catch函數(shù)。這樣我們就會(huì)以為是服務(wù)器的問題,實(shí)際上服務(wù)器是好的。
關(guān)鍵點(diǎn): 如果 后端程序,對這個(gè)參數(shù)是否有效做了判斷,返回其它的errorCode值,前端完全可以不用判斷是否有返回?cái)?shù)據(jù)。后端程序,直接拿一個(gè)數(shù)據(jù)庫中沒有的 選手id參數(shù) 去查找相應(yīng)的 信息,肯定沒有數(shù)據(jù),返回?cái)?shù)據(jù)到了前端頁面,對應(yīng)的字段就沒有了。
// 調(diào)接口后 執(zhí)行的函數(shù)
if (res.errorCode === 0) {
document.title = res.data.playName // 這里 沒有查詢到數(shù)據(jù),返回的對象里就沒有data這個(gè)屬性了。這里會(huì)直接報(bào)錯(cuò)
}
// 查詢不到這選手信息,返回的數(shù)據(jù)
{
errorCode: 0,
success: true,
value: "查詢成功"
}
正常查詢到數(shù)據(jù)后,返回的數(shù)據(jù)是 下面這樣的
{
data: {
playName: "張三",
age: 20,
},
errorCode: 0,
value: "查詢成功",
success: true
}
ajax的 file類型參數(shù)
1、ajax的參數(shù)如果需要發(fā)送的是文件(即文件流),直接填url肯定的沒用的,那只是一個(gè)字符串。我們可以通過發(fā)起本地文件的網(wǎng)絡(luò)請求,就可以獲取到對應(yīng)文件的數(shù)據(jù)流了。
(個(gè)人)分析:涉及文件 的前后端交互,有兩種方案。
一 種是ajax把對應(yīng)文件(如圖片)的url地址作為參數(shù)發(fā)給后臺(tái)服務(wù)器,由服務(wù)器對這個(gè)圖片文件發(fā)起網(wǎng)絡(luò)請求,獲得數(shù)據(jù)流。(這種方式要求,圖片文件必須在某個(gè)服務(wù)器上,后臺(tái)服務(wù)器發(fā)起網(wǎng)絡(luò)請求可以獲得對應(yīng)的文件),
第二種,就是發(fā)起本地網(wǎng)絡(luò)請求,獲得對應(yīng)文件的數(shù)據(jù)流。(這種方式開發(fā)中用的比較多,一般開發(fā)都是在本地。)
注意:ajax請求的對象(一般是文件)必須是在服務(wù)器中,即請求協(xié)議不能是 file:// 這種協(xié)議的。
2、get請求圖片,回調(diào)中返回的數(shù)據(jù)是一個(gè)文件流對象。ajax的參數(shù)必須的字符串,不能是對象(待驗(yàn)證)。
3、jQuery中ajax各個(gè)參數(shù) : https://www.cnblogs.com/qiufuwu618/archive/2012/12/20/2826190.html
原生 Fetch:https://www.jianshu.com/p/7762515f8d1a
1、fetch 本身就是 基于 promise 實(shí)現(xiàn)的,而ajax要使用promise的功能,必須先轉(zhuǎn)化為promise對象。
2、目前 fetch 使用的不是很多,后期在行補(bǔ)充
總結(jié)
以上是生活随笔為你收集整理的原生Ajax( XHR 和 Fetch )的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hadoop集群搭建-01前期准备
- 下一篇: 使用scrapy-redis 搭建分布式