對於前端來講,請求是前端平常工做必備的,經過請求才能與後端進行數據交互,尤爲在如今先後端分離的開發模式下,請求顯得就更加劇要。所以,對於前端開發者來講,掌握請求就很重要。下面將從http請求和常見的幾個請求技術作具體的講解css
XMLHttpRequest一開始只是微軟瀏覽器提供的一個接口,後來各大瀏覽器紛紛效仿也提供了這個接口,再後來W3C對它進行了標準化,按照標準先後能夠分爲兩個版本,具體闡述以下:html
//新建一個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 ); } };
在老版本中的,對應的具體屬性說明以下:前端
老版本由於不是統一的標準,各個瀏覽器廠商在實現的時候都有必定的差別,並且在存在一些缺陷:vue
爲了更好的使用XMLHttpRequest,w3school發佈了標準版本,該版本彌補了版本一的缺陷,也被各大瀏覽器廠商接受並實現。具體爲:node
固然,通常爲了友好的進行兼容各個瀏覽器,會採用對瀏覽器進行判斷並進行兼容性模式來獲取XMLHttpRequest的對象jquery
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 是一種與服務器交換數據的技術,能夠在不從新載入整個頁面的狀況下更新網頁的一部分,其實就是對XMLHttpRequest的封裝,能夠直接引入jquery工具包來進行調用ajax請求(jquery是一個js工具包,其特色是:寫得少,作得多),具體的ajax經常使用方式以下:ios
方法 | 描述 |
---|---|
$.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 的數組 |
固然,咱們能夠直接使用XMLHttpReqeust來進行實現本身的ajax封裝,具體代碼以下:es6
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.js的一款插件,它能夠經過XMLHttpRequest或JSONP發起請求並處理響應。也就是說,$.ajax能作的事情,vue-resource插件同樣也能作到,並且vue-resource的API更爲簡潔。另外,vue-resource還提供了很是有用的inteceptor功能,使用inteceptor能夠在請求前和請求後附加一些行爲,好比使用inteceptor在ajax請求時顯示loading界面。面試
客戶端請求方法 | 服務端處理方法 |
---|---|
this.$http.get(...) | Getxxx |
this.$http.post(...) | Postxxx |
this.$http.put(...) | Putxxx |
this.$http.delete(...) | Deletexxx |
參數 | 類型 | 描述 |
---|---|---|
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(url).then(function(response) { return response.json(); }).then(function(data) { console.log(data); }).catch(function(e) { console.log("Oops, error"); });
可配合es6的箭頭函數進行使用ajax
fetch(url).then(response => response.json()) .then(data => console.log(data)) .catch(e => console.log("Oops, error", e))
Axios 是一個基於 promise 的 HTTP 庫,能夠用在瀏覽器和 node.js 中
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.');
固然,不管選擇哪種方式都須要自身結合業務的須要和自個人認知,沒有哪一個絕對的優秀,也沒有哪一個絕對不優秀。根據自身的經驗以及相關資料的查找,總結了《前端常見面試》這個系列 ,後續若是有更多的內容,我也會逐步去更新或者補充這個系列,指望可以對你們都有所幫助,歡迎你們轉發和點贊關注。本系列的相關文章以下: