摘要:本文詳細(xì)講述如何使用原生和來實(shí)現(xiàn)。使用可以無刷新地向服務(wù)端發(fā)送請(qǐng)求接收服務(wù)端響應(yīng),并更新頁面。分別要用到的方法和方法。,,都是現(xiàn)在和未來解決異步的標(biāo)準(zhǔn)做法,可以完美搭配使用。這也是使用標(biāo)準(zhǔn)一大好處。
本文詳細(xì)講述如何使用原生 JS、jQuery 和 Fetch 來實(shí)現(xiàn) AJAX。
AJAX 即 Asynchronous JavaScript and XML,異步的 JavaScript 和 XML。使用 AJAX 可以無刷新地向服務(wù)端發(fā)送請(qǐng)求接收服務(wù)端響應(yīng),并更新頁面。
一、原生 JS 實(shí)現(xiàn) AJAXJS 實(shí)現(xiàn) AJAX 主要基于瀏覽器提供的 XMLHttpRequest(XHR)類,所有現(xiàn)代瀏覽器(IE7+、Firefox、Chrome、Safari 以及 Opera)均內(nèi)建 XMLHttpRequest 對(duì)象。
1. 獲取XMLHttpRequest對(duì)象// 獲取XMLHttpRequest對(duì)象 var xhr = new XMLHttpRequest();
如果需要兼容老版本的 IE (IE5, IE6) 瀏覽器,則可以使用 ActiveX 對(duì)象:
var xhr; if (window.XMLHttpRequest) { // Mozilla, Safari... xhr = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} } }2. 發(fā)送一個(gè) HTTP 請(qǐng)求
接下來,我們需要打開一個(gè)URL,然后發(fā)送這個(gè)請(qǐng)求。分別要用到 XMLHttpRequest 的 open() 方法和 send() 方法。
// GET var xhr; if (window.XMLHttpRequest) { // Mozilla, Safari... xhr = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} } } if (xhr) { xhr.open("GET", "/api?username=admin&password=root", true); xhr.send(null); }
// POST var xhr; if (window.XMLHttpRequest) { // Mozilla, Safari... xhr = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} } } if (xhr) { xhr.open("POST", "/api", true); // 設(shè)置 Content-Type 為 application/x-www-form-urlencoded // 以表單的形式傳遞數(shù)據(jù) xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send("username=admin&password=root"); }
open() 方法有三個(gè)參數(shù):
open() 的第一個(gè)參數(shù)是 HTTP 請(qǐng)求方式 – GET,POST,HEAD 或任何服務(wù)器所支持的您想調(diào)用的方式。按照HTTP規(guī)范,該參數(shù)要大寫;否則,某些瀏覽器(如Firefox)可能無法處理請(qǐng)求。有關(guān)HTTP請(qǐng)求方法的詳細(xì)信息可參考 https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
第二個(gè)參數(shù)是請(qǐng)求頁面的 URL。由于同源策略(Same origin policy)該頁面不能為第三方域名的頁面。同時(shí)一定要保證在所有的頁面中都使用準(zhǔn)確的域名,否則調(diào)用 open() 會(huì)得到 permission denied 的錯(cuò)誤提示。
第三個(gè)參數(shù)設(shè)置請(qǐng)求是否為異步模式。如果是 TRUE,JavaScript 函數(shù)將繼續(xù)執(zhí)行,而不等待服務(wù)器響應(yīng)。這就是 AJAX 中的 A。
如果第一個(gè)參數(shù)是 GET,則可以直接將參數(shù)放在 url 后面,如:http://nodejh.com/api?name=admint&password=root。
如果第一個(gè)參數(shù)是 POST,則需要將參數(shù)寫在 send() 方法里面。send() 方法的參數(shù)可以是任何想送給服務(wù)器的數(shù)據(jù)。這時(shí)數(shù)據(jù)要以字符串的形式送給服務(wù)器,如:name=admint&password=root。或者也可以傳遞 JSON 格式的數(shù)據(jù):
// 設(shè)置 Content-Type 為 application/json xhr.setRequestHeader("Content-Type", "application/json"); // 傳遞 JSON 字符串 xhr.send(JSON.stringify({ username:"admin", password:"root" }));
如果不設(shè)置請(qǐng)求頭,原生 AJAX 會(huì)默認(rèn)使用 Content-Type 是 text/plain;charset=UTF-8 的方式發(fā)送數(shù)據(jù)。
關(guān)于 Content-Type 更詳細(xì)的內(nèi)容,將在以后的文章中解釋說明。
3. 處理服務(wù)器的響應(yīng)當(dāng)發(fā)送請(qǐng)求時(shí),我們需要指定如何處理服務(wù)器的響應(yīng),我們需要用到 onreadystatechange 屬性來檢測(cè)服務(wù)器的響應(yīng)狀態(tài)。使用 onreadystatechange 有兩種方式,一是直接 onreadystatechange 屬性指定一個(gè)可調(diào)用的函數(shù)名,二是使用一個(gè)匿名函數(shù):
// 方法一 指定可調(diào)用的函數(shù) xhr.onreadystatechange = onReadyStateChange; function onReadyStateChange() { // do something } // 方法二 使用匿名函數(shù) xhr.onreadystatechange = function(){ // do the thing };
接下來我們需要在內(nèi)部利用 readyState 屬性來獲取當(dāng)前的狀態(tài),當(dāng) readyState 的值為 4,就意味著一個(gè)完整的服務(wù)器響應(yīng)已經(jīng)收到了,接下來就可以處理該響應(yīng):
// readyState的取值如下 // 0 (未初始化) // 1 (正在裝載) // 2 (裝載完畢) // 3 (交互中) // 4 (完成) if (xhr.readyState === 4) { // everything is good, the response is received } else { // still not ready }
完整代碼如下:
// POST var xhr; if (window.XMLHttpRequest) { // Mozilla, Safari... xhr = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} } } if (xhr) { xhr.onreadystatechange = onReadyStateChange; xhr.open("POST", "/api", true); // 設(shè)置 Content-Type 為 application/x-www-form-urlencoded // 以表單的形式傳遞數(shù)據(jù) xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send("username=admin&password=root"); } // onreadystatechange 方法 function onReadyStateChange() { // 該函數(shù)會(huì)被調(diào)用四次 console.log(xhr.readyState); if (xhr.readyState === 4) { // everything is good, the response is received if (xhr.status === 200) { console.log(xhr.responseText); } else { console.log("There was a problem with the request."); } } else { // still not ready console.log("still not ready..."); } }
當(dāng)然我們可以用onload來代替onreadystatechange等于4的情況,因?yàn)閛nload只在狀態(tài)為4的時(shí)候才被調(diào)用,代碼如下:
xhr.onload = function () { // 調(diào)用onload if (xhr.status === 200) { // status為200表示請(qǐng)求成功 console.log("執(zhí)行成功"); } else { console.log("執(zhí)行出錯(cuò)"); } }
然而需要注意的是,IE對(duì) onload 屬性的支持并不友好。除了 onload 還有以下幾個(gè)屬性也可以用來監(jiān)測(cè)響應(yīng)狀態(tài):
onloadstart
onprogress
onabort
ontimeout
onerror
onloadend
二、 jQuery 實(shí)現(xiàn) AJAXjQuery 作為一個(gè)使用人數(shù)最多的庫,其 AJAX 很好的封裝了原生 AJAX 的代碼,在兼容性和易用性方面都做了很大的提高,讓 AJAX 的調(diào)用變得非常簡單。下面便是一段簡單的 jQuery 的 AJAX 代碼:
$.ajax({ method: "POST", url: "/api", data: { username: "admin", password: "root" } }) .done(function(msg) { alert( "Data Saved: " + msg ); });
對(duì)比原生 AJAX 的實(shí)現(xiàn),使用 jQuery 就異常簡單了。當(dāng)然我們平時(shí)用的最多的,是下面兩種更簡單的方式:
// GET $.get("/api", function(res) { // do something }); // POST var data = { username: "admin", password: "root" }; $.post("/api", data, function(res) { // do something });三、Fetch API
使用 jQuery 雖然可以大大簡化 XMLHttpRequest 的使用,但 XMLHttpRequest 本質(zhì)上但并不是一個(gè)設(shè)計(jì)優(yōu)良的 API:
不符合關(guān)注分離(Separation of Concerns)的原則
配置和調(diào)用方式非常混亂
使用事件機(jī)制來跟蹤狀態(tài)變化
基于事件的異步模型沒有現(xiàn)代的 Promise,generator/yield,async/await 友好
Fetch API 旨在修正上述缺陷,它提供了與 HTTP 語義相同的 JS 語法,簡單來說,它引入了 fetch() 這個(gè)實(shí)用的方法來獲取網(wǎng)絡(luò)資源。
Fetch 的瀏覽器兼容圖如下:
原生支持率并不高,幸運(yùn)的是,引入下面這些 polyfill 后可以完美支持 IE8+:
由于 IE8 是 ES3,需要引入 ES5 的 polyfill: es5-shim, es5-sham
引入 Promise 的 polyfill: es6-promise
引入 fetch 探測(cè)庫:fetch-detector
引入 fetch 的 polyfill: fetch-ie8
可選:如果你還使用了 jsonp,引入 fetch-jsonp
可選:開啟 Babel 的 runtime 模式,現(xiàn)在就使用 async/await
1. 一個(gè)使用 Fetch 的例子先看一個(gè)簡單的 Fetch API 的例子 ? :
fetch("/api").then(function(response) { return response.json(); }).then(function(data) { console.log(data); }).catch(function(error) { console.log("Oops, error: ", error); });
使用 ES6 的箭頭函數(shù)后:
fetch("/api").then(response => response.json()) .then(data => console.log(data)) .catch(error => console.log("Oops, error: ", error))
可以看出使用Fetch后我們的代碼更加簡潔和語義化,鏈?zhǔn)秸{(diào)用的方式也使其更加流暢和清晰。但這種基于 Promise 的寫法還是有 Callback 的影子,我們還可以用 async/await 來做最終優(yōu)化:
async function() { try { let response = await fetch(url); let data = response.json(); console.log(data); } catch (error) { console.log("Oops, error: ", error); } }
使用 await 后,寫代碼就更跟同步代碼一樣。await 后面可以跟 Promise 對(duì)象,表示等待 Promise resolve() 才會(huì)繼續(xù)向下執(zhí)行,如果 Promise 被 reject() 或拋出異常則會(huì)被外面的 try...catch 捕獲。
Promise,generator/yield,await/async 都是現(xiàn)在和未來 JS 解決異步的標(biāo)準(zhǔn)做法,可以完美搭配使用。這也是使用標(biāo)準(zhǔn) Promise 一大好處。
2. 使用 Fetch 的注意事項(xiàng)Fetch 請(qǐng)求默認(rèn)是不帶 cookie,需要設(shè)置 fetch(url, {credentials: "include"})`
服務(wù)器返回 400,500 錯(cuò)誤碼時(shí)并不會(huì) reject,只有網(wǎng)絡(luò)錯(cuò)誤這些導(dǎo)致請(qǐng)求不能完成時(shí),fetch 才會(huì)被 reject
接下來將上面基于 XMLHttpRequest 的 AJAX 用 Fetch 改寫:
var options = { method: "POST", headers: { "Accept": "application/json", "Content-Type": "application/json" }, body: JSON.stringify({ username: "admin", password: "root" }), credentials: "include" }; fetch("/api", options).then(response => response.json()) .then(data => console.log(data)) .catch(error => console.log("Oops, error: ", error))
Github Issue: https://github.com/nodejh/nodejh.github.io/issues/15
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/86672.html
摘要:我們都知道因?yàn)橥床呗缘膯栴},瀏覽器的請(qǐng)求是可能隨便跨域的一定要有跨域頭或者借助,但是,中可以設(shè)置為不跨域,如下所示這樣之后我們會(huì)得到一個(gè)為的返回。 免費(fèi)幫忙內(nèi)推阿里等各大IT公司的崗位,有興趣可以帶簡歷加微信angeltune 引言 前端技術(shù)真是一個(gè)發(fā)展飛快的領(lǐng)域,我三年前入職的時(shí)候只有原生XHR和Jquery ajax,我們還曾被JQuery 1.9版本版本以下不支持大文件請(qǐng)求這個(gè)...
摘要:請(qǐng)求默認(rèn)會(huì)攜帶同源請(qǐng)求的,而跨域請(qǐng)求則不會(huì)攜帶,設(shè)置的的屬性為將允許攜帶跨域。類型請(qǐng)求成功后的回調(diào)函數(shù)。另外,同樣提供了在環(huán)境下的支持,可謂是網(wǎng)絡(luò)請(qǐng)求的首選方案。當(dāng)網(wǎng)絡(luò)故障時(shí)或請(qǐng)求被阻止時(shí),才會(huì)標(biāo)記為,如跨域不存在,網(wǎng)絡(luò)異常等會(huì)觸發(fā)。 一、前端進(jìn)行網(wǎng)絡(luò)請(qǐng)求的關(guān)注點(diǎn) 大多數(shù)情況下,在前端發(fā)起一個(gè)網(wǎng)絡(luò)請(qǐng)求我們只需關(guān)注下面幾點(diǎn): 傳入基本參數(shù)(url,請(qǐng)求方式) 請(qǐng)求參數(shù)、請(qǐng)求參數(shù)類型 設(shè)...
摘要:所以本文將介紹兩個(gè)目前常用的獲取服務(wù)器數(shù)據(jù)的庫和。隨著作者尤雨溪發(fā)布消息,不再繼續(xù)維護(hù)并推薦大家使用開始,進(jìn)入了很多人的目光。脫離了,是基于設(shè)計(jì)。如果要詳細(xì)了解的應(yīng)用,推薦閱讀教程和規(guī)范。歡迎大家前往騰訊云+社區(qū),獲取更多騰訊海量技術(shù)實(shí)踐干貨哦~ 本文由前端林子發(fā)表于云+社區(qū)專欄 隨著前端技術(shù)的發(fā)展,請(qǐng)求服務(wù)器數(shù)據(jù)的方法早已不局限于ajax、jQuery的ajax方法。各種js庫已如雨后...
摘要:前端最基礎(chǔ)的就是。的原理瀏覽器發(fā)送請(qǐng)求,服務(wù)器給出響應(yīng)。保持之前的界面不變化。的核心創(chuàng)建一個(gè)對(duì)象,用于發(fā)起請(qǐng)求設(shè)置為請(qǐng)求,請(qǐng)求發(fā)送請(qǐng)求。 前端最基礎(chǔ)的就是 HTML+CSS+Javascript。掌握了這三門技術(shù)就算入門,但也僅僅是入門,現(xiàn)在前端開發(fā)的定義已經(jīng)遠(yuǎn)遠(yuǎn)不止這些。前端小課堂(HTML/CSS/JS),本著提升技術(shù)水平,打牢基礎(chǔ)知識(shí)的中心思想,我們開課啦(每周四)。 ajax ...
摘要:前端最基礎(chǔ)的就是。的原理瀏覽器發(fā)送請(qǐng)求,服務(wù)器給出響應(yīng)。保持之前的界面不變化。的核心創(chuàng)建一個(gè)對(duì)象,用于發(fā)起請(qǐng)求設(shè)置為請(qǐng)求,請(qǐng)求發(fā)送請(qǐng)求。 前端最基礎(chǔ)的就是 HTML+CSS+Javascript。掌握了這三門技術(shù)就算入門,但也僅僅是入門,現(xiàn)在前端開發(fā)的定義已經(jīng)遠(yuǎn)遠(yuǎn)不止這些。前端小課堂(HTML/CSS/JS),本著提升技術(shù)水平,打牢基礎(chǔ)知識(shí)的中心思想,我們開課啦(每周四)。 ajax ...
閱讀 1357·2021-09-02 10:19
閱讀 1101·2019-08-26 13:25
閱讀 2108·2019-08-26 11:37
閱讀 2413·2019-08-26 10:18
閱讀 2676·2019-08-23 16:43
閱讀 2989·2019-08-23 16:25
閱讀 775·2019-08-23 15:53
閱讀 3297·2019-08-23 15:11