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