原生JS請求
現代瀏覽器,最開始與服務器交換數據,都是通過XMLHttpRequest對象。它可以使用JSON、XML、HTML和text文本等格式發送和接收數據。
首先我們先把原生的請求封裝一下:
xmlhttp=new XMLHttpRequest()
function obj2str(data) { data = data || {}; // 如果沒有傳參, 為了添加隨機因⼦,必須⾃⼰創建⼀個對象 data.t = new Date().getTime(); var res = []; for (var key in data) { //在URL中是不可以出現中⽂的,如果出現了中⽂需要轉碼,可以調⽤encodeURIComponent⽅法,URL中 res.push(encodeURIComponent(key) + "=" + encodeURIComponent(data[key])); } return res.join("&"); } function ajax(option) { var str = obj2str(option.data);//key=value&key=value; var xmlhttp, timer; if (option.type.toLowerCase() === "get") {//toLowerCase將⼤寫轉化為⼩寫 xmlhttp.open(option.type, option.url + "?" + str, true) xmlhttp.send(); } else { xmlhttp.open(option.type, option.url, true); //注意點:以下代碼必須放在open和send之間 xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xmlhttp.send(str); } xmlhttp.onreadystatechange = function (ev2) { if (xmlhttp.readyState === 4) { clearInterval(timer); //判斷是否請求成功(Http狀態碼⼤於等於200,且⼩於300,和狀態碼等於304為請求成功) if (xmlhttp.status >= 200 && xmlhttp.status < 300 || xmlhttp.status === 304) { option.success(xmlhttp); } else { option.error(xmlhttp); } } }; if (option.timeout) { timer = setInterval(function () { console.log("中斷請求"); xmlhttp.abort(); clearInterval(timer); }, option.timeout); } }
使用:
ajax({ url:"http://server-name/login", type:'post', data:{ username:'username', password:'password' }, dataType:'json', timeout:10000, contentType:"application/json", success:function(data){ 。。。。。。//服務器返回響應,根據響應結果,分析是否登錄成功 }, //異常處理 error:function(e){ console.log(e); } })
優點:
- 不重新加載頁面的情況下更新網頁
- 在頁面已加載后從服務器請求/接收數據
- 在后台向服務器發送數據。
缺點:
- 使用起來也比較繁瑣,需要設置很多值。
- 早期的IE瀏覽器有自己的實現,這樣需要寫兼容代碼。
Jq中的ajax:
為了更快捷的操作DOM,並且規避一些瀏覽器兼容問題,產生了jQuery
。它里面的AJAX
請求也兼容了各瀏覽器,可以有簡單易用的方法$.get
,$.post
。簡單點說,就是對XMLHttpRequest
對象的封裝。
$.ajax({ type: 'POST', url: url, data: data, dataType: dataType, success: function () {}, error: function () {} })
優點:
- 對原生
XHR
的封裝,做了兼容處理,簡化了使用。 - 增加了對
JSONP
的支持,可以簡單處理部分跨域。
缺點:
- 如果有多個請求,並且有依賴關系的話,容易形成回調地獄。
- 本身是針對MVC的編程,不符合現在前端MVVM的浪潮。
- ajax是jQuery中的一個方法。如果只是要使用ajax卻要引入整個jQuery非常的不合理。
Axios:
Axios
是一個基於promise
的HTTP
庫,可以用在瀏覽器和 node.js
中。它本質也是對原生XMLHttpRequest
的封裝,只不過它是Promise的實現版本,符合最新的ES規范。
axios({ method: 'post', url: '/user/12345', data: { firstName: 'liu', lastName: 'weiqin' } }) .then(res => console.log(res)) .catch(err => console.log(err))
優點:
- 從瀏覽器中創建
XMLHttpRequests
- 從
node.js
創建http
請求 - 支持
Promise
API - 攔截請求和響應
- 轉換請求數據和響應數據
- 取消請求
- 自動轉換
JSON
數據 - 客戶端支持防御
XSRF
缺點:
- 只持現代代瀏覽器.
fetch:
Fetch API
提供了一個 JavaScript
接口,用於訪問和操作HTTP
管道的部分,例如請求和響應。它還提供了一個全局fetch()
方法,該方法提供了一種簡單,合理的方式來跨網絡異步獲取資源。fetch
是低層次的API,代替XHR
,可以輕松處理各種格式,非文本化格式。可以很容易的被其他技術使用,例如Service Workers
。但是想要很好的使用fetch
,需要做一些封裝處理。
fetch('http://example.com/movies.json') .then(function(response) { return response.json(); }) .then(function(myJson) { console.log(myJson); });
fetch
目前遇到的問題:
fetch
只對網絡請求報錯,對400
,500
都當做成功的請求,需要封裝去處理fetch
默認不會帶cookie
,需要添加配置項。fetch
不支持abort
,不支持超時控制,使用setTimeout
及Promise.reject
的實現超時控制並不能阻止請求過程繼續在后台運行,造成了流量的浪費。fetch
沒有辦法原生監測請求的進度,而XHR
可以。
請注意,fetch規范與jQuery.ajax()主要有兩種方式的不同,牢記: -. 當接收到一個代表錯誤的 HTTP 狀態碼時,從 fetch()返回的 Promise 不會被標記為 reject, 即使該 HTTP 響應的狀態碼是 404 或 500。相反,它會將 Promise 狀態標記為 resolve (但是會將 resolve的返回值的 ok 屬性設置為 false ),僅當網絡故障時或請求被阻止時,才會標記為 reject。 -. 默認情況下,fetch 不會從服務端發送或接收任何 cookies, 如果站點依賴於用戶 session,則會導致未經認證的請求(要發送 cookies,必須設置 credentials 選項)。