前端http請求和常見的幾個請求技術做具體的講解


對於前端來說,請求是前端日常工作必備的,通過請求才能與后端進行數據交互,尤其在現在前后端分離的開發模式下,請求顯得就更加重要。因此,對於前端開發者來說,掌握請求就很重要。下面將從http請求和常見的幾個請求技術做具體的講解

 

一、XMLHttpRequest

        XMLHttpRequest一開始只是微軟瀏覽器提供的一個接口,后來各大瀏覽器紛紛效仿也提供了這個接口,再后來W3C對它進行了標准化,按照標准前后可以分為兩個版本,具體闡述如下:

版本以(老版本):
//新建一個XMLHttpRequest對象 var xhr=new XMLHttpRequest(); //進行請求 xhr.open('GET', 'url'); xhr.send(); //等待服務器響應 xhr.onreadystatechange = function(){ //該函數會被調用四次,因此需要判斷狀態是否為4 if ( xhr.readyState == 4 && xhr.status == 200 ) { alert( xhr.responseText ); } else { alert( xhr.statusText ); } };

        在老版本中的,對應的具體屬性說明如下:

  1. xhr.readyState:XMLHttpRequest對象的狀態,等於4表示數據已經接收完畢。
  2. xhr.status:服務器返回的狀態碼,等於200表示一切正常。
  3. xhr.responseText:服務器返回的文本數據
  4. xhr.responseXML:服務器返回的XML格式的數據
  5. xhr.statusText:服務器返回的狀態文本。

        老版本因為不是統一的標准,各個瀏覽器廠商在實現的時候都有一定的差異,而且在存在一些缺陷:

  1. 只支持文本數據的傳送,無法用來讀取和上傳二進制文件。
  2. 傳送和接收數據時,沒有進度信息,只能提示有沒有完成。
  3. 受到"同域限制"(Same Origin Policy),只能向同一域名的服務器請求數據。
版本二(標准后的版本):

        為了更好的使用XMLHttpRequest,w3school發布了標准版本,該版本彌補了版本一的缺陷,也被各大瀏覽器廠商接受並實現。具體為:

  1. 可以設置HTTP請求的時限。
  2. 可以使用FormData對象管理表單數據。
  3. 可以上傳文件。
  4. 可以請求不同域名下的數據(跨域請求)。
  5. 可以獲取服務器端的二進制數據。
  6. 可以獲得數據傳輸的進度信息。

當然,一般為了友好的進行兼容各個瀏覽器,會采用對瀏覽器進行判斷並進行兼容性模式來獲取XMLHttpRequest的對象

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'); //IE5,6 } catch (e) {} } } // 請求成功回調函數 xhr.onload = e => { console.log('request success'); }; // 請求結束 xhr.onloadend = e => { console.log('request loadend'); }; // 請求出錯 xhr.onerror = e => { console.log('request error'); }; // 請求超時 xhr.ontimeout = e => { console.log('request timeout'); }; // 請求回調函數.XMLHttpRequest標准又分為Level 1和Level 2,這是Level 1和的回調處理方式 // xhr.onreadystatechange = () => { // if (xhr.readyState !== 4) { // return; // } // const status = xhr.status; // if ((status >= 200 && status < 300) || status === 304) { // console.log('request success'); // } else { // console.log('request error'); // } // }; xhr.timeout = 0; // 設置超時時間,0表示永不超時 // 初始化請求 xhr.open('GET/POST/DELETE/...', '/url', true || false); // 設置期望的返回數據類型 'json' 'text' 'document' ... xhr.responseType = ''; // 設置請求頭 xhr.setRequestHeader('', ''); // 發送請求 xhr.send(null || new FormData || 'a=1&b=2' || 'json字符串');

 

二、ajax請求

        AJAX 是一種與服務器交換數據的技術,可以在不重新載入整個頁面的情況下更新網頁的一部分,其實就是對XMLHttpRequest的封裝,可以直接引入jquery工具包來進行調用ajax請求(jquery是一個js工具包,其特點是:寫得少,做得多),具體的ajax常用方式如下:

方法 描述
$.ajax() 執行異步 AJAX 請求
$.ajaxPrefilter() 在每個請求發送之前且被 $.ajax() 處理之前,處理自定義 Ajax 選項或修改已存在選項
$.ajaxSetup() 為將來的 AJAX 請求設置默認值
$.ajaxTransport() 創建處理 Ajax 數據實際傳送的對象
$.get() 使用 AJAX 的 HTTP GET 請求從服務器加載數據
$.getJSON() 使用 HTTP GET 請求從服務器加載 JSON 編碼的數據
$.getScript() 使用 AJAX 的 HTTP GET 請求從服務器加載並執行 JavaScript
$.param() 創建數組或對象的序列化表示形式(可用於 AJAX 請求的 URL 查詢字符串)
$.post() 使用 AJAX 的 HTTP POST 請求從服務器加載數據
ajaxComplete() 規定 AJAX 請求完成時運行的函數
ajaxError() 規定 AJAX 請求失敗時運行的函數
ajaxSend() 規定 AJAX 請求發送之前運行的函數
ajaxStart() 規定第一個 AJAX 請求開始時運行的函數
ajaxStop() 規定所有的 AJAX 請求完成時運行的函數
ajaxSuccess() 規定 AJAX 請求成功完成時運行的函數
load() 從服務器加載數據,並把返回的數據放置到指定的元素中
serialize() 編碼表單元素集為字符串以便提交
serializeArray() 編碼表單元素集為 names 和 values 的數組
優點:
  • 對原生XHR的封裝
  • 針對MVC的編程
  • 完美的兼容性
  • 支持jsonp
缺點:
  • 不符合MVVM
  • 異步模型不夠現代,不支持鏈式,代碼可讀性差
  • 整個Jquery太大,引入成本過高

        當然,我們可以直接使用XMLHttpReqeust來進行實現自己的ajax封裝,具體代碼如下:

const http = {
  /** * js封裝ajax請求 * >>使用new XMLHttpRequest 創建請求對象,所以不考慮低端IE瀏覽器(IE6及以下不支持XMLHttpRequest) * >>使用es6語法,如果需要在正式環境使用,則可以用babel轉換為es5語法 https://babeljs.cn/docs/setup/#installation * @param settings 請求參數模仿jQuery ajax * 調用該方法,data參數需要和請求頭Content-Type對應 * Content-Type data 描述 * application/x-www-form-urlencoded 'name=哈哈&age=12'或{name:'哈哈',age:12} 查詢字符串,用&分割 * application/json name=哈哈&age=12' json字符串 * multipart/form-data new FormData() FormData對象,當為FormData類型,不要手動設置Content-Type * 注意:請求參數如果包含日期類型.是否能請求成功需要后台接口配合 */ ajax: (settings = {}) => { // 初始化請求參數 let _s = Object.assign({ url: '', // string type: 'GET', // string 'GET' 'POST' 'DELETE' dataType: 'json', // string 期望的返回數據類型:'json' 'text' 'document' ... async: true, // boolean true:異步請求 false:同步請求 required data: null, // any 請求參數,data需要和請求頭Content-Type對應 headers: {}, // object 請求頭 timeout: 1000, // string 超時時間:0表示不設置超時 beforeSend: (xhr) => { }, success: (result, status, xhr) => { }, error: (xhr, status, error) => { }, complete: (xhr, status) => { } }, settings); // 參數驗證 if (!_s.url || !_s.type || !_s.dataType || !_s.async) { alert('參數有誤'); return; } // 創建XMLHttpRequest請求對象 let xhr = new XMLHttpRequest(); // 請求開始回調函數 xhr.addEventListener('loadstart', e => { _s.beforeSend(xhr); }); // 請求成功回調函數 xhr.addEventListener('load', e => { const status = xhr.status; if ((status >= 200 && status < 300) || status === 304) { let result; if (xhr.responseType === 'text') { result = xhr.responseText; } else if (xhr.responseType === 'document') { result = xhr.responseXML; } else { result = xhr.response; } // 注意:狀態碼200表示請求發送/接受成功,不表示業務處理成功 _s.success(result, status, xhr); } else { _s.error(xhr, status, e); } }); // 請求結束 xhr.addEventListener('loadend', e => { _s.complete(xhr, xhr.status); }); // 請求出錯 xhr.addEventListener('error', e => { _s.error(xhr, xhr.status, e); }); // 請求超時 xhr.addEventListener('timeout', e => { _s.error(xhr, 408, e); }); let useUrlParam = false; let sType = _s.type.toUpperCase(); // 如果是"簡單"請求,則把data參數組裝在url上 if (sType === 'GET' || sType === 'DELETE') { useUrlParam = true; _s.url += http.getUrlParam(_s.url, _s.data); } // 初始化請求 xhr.open(_s.type, _s.url, _s.async); // 設置期望的返回數據類型 xhr.responseType = _s.dataType; // 設置請求頭 for (const key of Object.keys(_s.headers)) { xhr.setRequestHeader(key, _s.headers[key]); } // 設置超時時間 if (_s.async && _s.timeout) { xhr.timeout = _s.timeout; } // 發送請求.如果是簡單請求,請求參數應為null.否則,請求參數類型需要和請求頭Content-Type對應 xhr.send(useUrlParam ? null : http.getQueryData(_s.data)); }, // 把參數data轉為url查詢參數 getUrlParam: (url, data) => { if (!data) { return ''; } let paramsStr = data instanceof Object ? http.getQueryString(data) : data; return (url.indexOf('?') !== -1) ? paramsStr : '?' + paramsStr; }, // 獲取ajax請求參數 getQueryData: (data) => { if (!data) { return null; } if (typeof data === 'string') { return data; } if (data instanceof FormData) { return data; } return http.getQueryString(data); }, // 把對象轉為查詢字符串 getQueryString: (data) => { let paramsArr = []; if (data instanceof Object) { Object.keys(data).forEach(key => { let val = data[key]; // todo 參數Date類型需要根據后台api酌情處理 if (val instanceof Date) { // val = dateFormat(val, 'yyyy-MM-dd hh:mm:ss'); } paramsArr.push(encodeURIComponent(key) + '=' + encodeURIComponent(val)); }); } return paramsArr.join('&'); } }

 

三、vue-resource請求

        vue-resource是Vue.js的一款插件,它可以通過XMLHttpRequest或JSONP發起請求並處理響應。也就是說,$.ajax能做的事情,vue-resource插件一樣也能做到,而且vue-resource的API更為簡潔。另外,vue-resource還提供了非常有用的inteceptor功能,使用inteceptor可以在請求前和請求后附加一些行為,比如使用inteceptor在ajax請求時顯示loading界面。

特點
  1. 體積小
    vue-resource非常小巧,在壓縮以后只有大約12KB,服務端啟用gzip壓縮后只有4.5KB大小,這遠比jQuery的體積要小得多。
  2. 支持主流的瀏覽器
    和Vue.js一樣,vue-resource除了不支持IE 9以下的瀏覽器,其他主流的瀏覽器都支持。
  3. 支持Promise API和URI Templates
    Promise是ES6的特性,Promise的中文含義為“先知”,Promise對象用於異步計算。
    URI Templates表示URI模板,有些類似於ASP.NET MVC的路由模板。
  4. 支持攔截器
    攔截器是全局的,攔截器可以在請求發送前和發送請求后做一些處理。
    攔截器在一些場景下會非常有用,比如請求發送前在headers中設置access_token,或者在請求失敗時,提供共通的處理方式。
常用api
  1. get(url, [options])
  2. head(url, [options])
  3. delete(url, [options])
  4. jsonp(url, [options])
  5. post(url, [body], [options])
  6. put(url, [body], [options])
  7. patch(url, [body], [options])
客戶端請求方法 服務端處理方法
this.$http.get(...) Getxxx
this.$http.post(...) Postxxx
this.$http.put(...) Putxxx
this.$http.delete(...) Deletexxx
option詳解
參數 類型 描述
url string 請求的URL
method string 請求的HTTP方法,例如:'GET', 'POST'或其他HTTP方法
body Object, FormData string request body
params Object 請求的URL參數對象
headers Object request header
timeout number 單位為毫秒的請求超時時間 (0 表示無超時時間)
before function(request) 請求發送前的處理函數,類似於jQuery的beforeSend函數
progress function(event) ProgressEvent回調處理函數
credentials boolean 表示跨域請求時是否需要使用憑證
emulateHTTP boolean 發送PUT, PATCH, DELETE請求時以HTTP POST的方式發送,並設置請求頭的X-HTTP-Method-Override
emulateJSON boolean 將request body以application/x-www-form-urlencoded content type發送

四、fetch

  1. fetch是基於promise實現的,也可以結合async/await
  2. fetch請求默認是不帶cookie的,需要設置fetch(URL,{credentials:’include’})。 
  3. Credentials有三種參數:same-origin,include,*
  4. 服務器返回400 500 狀態碼時並不會reject,只有網絡出錯導致請求不能完成時,fetch才會被reject
  5. 所有版本的 IE 均不支持原生 Fetch
  6. fetch是widow的一個方法
fetch(url).then(function(response) { return response.json(); }).then(function(data) { console.log(data); }).catch(function(e) { console.log("Oops, error"); });

        可配合es6的箭頭函數進行使用

fetch(url).then(response => response.json()) .then(data => console.log(data)) .catch(e => console.log("Oops, error", e))

電腦刺綉綉花廠 http://www.szhdn.com 廣州品牌設計公司https://www.houdianzi.com

五、axios

        Axios 是一個基於 promise 的 HTTP 庫,可以用在瀏覽器和 node.js 中

特點
  • 從瀏覽器中創建XMLHttpRequests
  • 從 node.js 創建http請求
  • 支持PromiseAPI
  • 攔截請求和響應
  • 轉換請求數據和響應數據
  • 取消請求
  • 自動轉換 JSON 數據
  • 客戶端支持防御XSRF
常用api
  1. axios.request(config)
  2. axios.get(url[, config])
  3. axios.delete(url[, config])
  4. axios.head(url[, config])
  5. axios.options(url[, config])
  6. axios.post(url[, data[, config]])
  7. axios.put(url[, data[, config]])
  8. axios.patch(url[, data[, config]]
實例

get請求

// 為給定 ID 的 user 創建請求 axios.get('/user?ID=12345') .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }); // 可選地,上面的請求可以這樣做 axios.get('/user', { params: { ID: 12345 } }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });

post請求

axios.post('/user', { firstName: 'Fred', lastName: 'Flintstone' }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });

並發請求

function getUserAccount() { return axios.get('/user/12345'); } function getUserPermissions() { return axios.get('/user/12345/permissions'); } axios.all([getUserAccount(), getUserPermissions()]) .then(axios.spread(function (acct, perms) { // 兩個請求現在都執行完成 }));

攔截器

// 添加請求攔截器 axios.interceptors.request.use(function (config) { // 在發送請求之前做些什么 return config; }, function (error) { // 對請求錯誤做些什么 return Promise.reject(error); }); // 添加響應攔截器 axios.interceptors.response.use(function (response) { // 對響應數據做點什么 return response; }, function (error) { // 對響應錯誤做點什么 return Promise.reject(error); });

取消請求

 
var CancelToken = axios.CancelToken; var source = CancelToken.source(); axios.get('/user/12345', { cancelToken: source.token }).catch(function(thrown) { if (axios.isCancel(thrown)) { console.log('Request canceled', thrown.message); } else { // 處理錯誤 } }); // 取消請求(message 參數是可選的) source.cancel('Operation canceled by the user.');


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM