对于前端来讲,请求是前端平常工做必备的,经过请求才能与后端进行数据交互,尤为在如今先后端分离的开发模式下,请求显得就更加剧要。所以,对于前端开发者来讲,掌握请求就很重要。下面将从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.');
固然,不管选择哪种方式都须要自身结合业务的须要和自个人认知,没有哪一个绝对的优秀,也没有哪一个绝对不优秀。根据自身的经验以及相关资料的查找,总结了《前端常见面试》这个系列 ,后续若是有更多的内容,我也会逐步去更新或者补充这个系列,指望可以对你们都有所帮助,欢迎你们转发和点赞关注。本系列的相关文章以下: