缺点:
不符合MVVM
异步模型不够现代,不支持链式,代码可读性差
整个Jquery太大,引入成本过高
当然,我们可以直接使用XMLHttpReqeust来进行实现自己的ajax封装,具体代码如下:
consthttp = {
/**
* js封装ajax请求
* >>使用new 创建请求对象,所以不考虑低端IE浏览器(IE6及以下不支持)
* >>使用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;
}
// 创建请求对象
letxhr = new;
// 请求开始回调函数
xhr.addEventListener( 'loadstart', e => {
_s.beforeSend(xhr);
});
// 请求成功回调函数
xhr.addEventListener( 'load', e => {
conststatus = xhr.status;
if((status >= 200&& status < 300) || status === 304) {
letresult;
if(xhr.responseType === 'text') {
result = xhr.responseText;
} elseif(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);
});
letuseUrlParam = false;
letsType = _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( constkey 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'';
}
letparamsStr = data instanceofObject? http.getQueryString(data) : data;
return(url.indexOf( '?') !== -1) ? paramsStr : '?'+ paramsStr;
},
// 获取ajax请求参数
getQueryData: (data) => {
if(!data) {
returnnull;
}
if( typeofdata === 'string') {
returndata;
}
if(data instanceofFormData) {
returndata;
}
returnhttp.getQueryString(data);
},
// 把对象转为查询字符串
getQueryString: (data) => {
letparamsArr = [];
if(data instanceofObject) {
Object.keys(data).forEach(key => {
letval = data[key];
// todo 参数Date类型需要根据后台api酌情处理
if(val instanceofDate) {
// val = dateFormat(val, 'yyyy-MM-dd hh:mm:ss');
}
paramsArr.push( encodeURIComponent(key) + '='+ encodeURIComponent(val));
});
}
returnparamsArr.join( '&');
}
}
No.3
vue-resource 请求
vue-resource是Vue.js的一款插件,它可以通过或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
get(url, [options])
head(url, [options])
delete(url, [options])
jsonp(url, [options])
post(url, [body], [options])
put(url, [body], [options])
patch(url, [body], [options])
option 详解
No.4
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) {
returnresponse.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))
No.5
axios
Axios是一个基于promise的HTTP库,可以用在浏览器和node.js中
特点:
从浏览器中创建s
从node.js创建http请求
支持PromiseAPI
拦截请求和响应
转换请求数据和响应数据
取消请求
自动转换JSON数据
客户端支持防御XSRF常用 api:
axios.request(config)
axios.get(url[, config])
axios.delete(url[, config])
axios.head(url[, config])
axios.options(url[, config])
axios.post(url[, data[, config]])
axios.put(url[, data[, config]])
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);
});
并发请求
functiongetUserAccount{
returnaxios.get('/user/12345');
}
functiongetUserPermissions{
returnaxios.get('/user/12345/permissions');
}
axios. all([getUserAccount, getUserPermissions])
. then(axios.spread( function(acct, perms) {
// 两个请求现在都执行完成
}));
拦截器
// 添加请求拦截器
axios.interceptors.request.use( function(config) {
// 在发送请求之前做些什么
returnconfig;
}, function(error) {
// 对请求错误做些什么
returnPromise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use( function(response) {
// 对响应数据做点什么
returnresponse;
}, function(error) {
// 对响应错误做点什么
returnPromise.reject(error);
});
取消请求
varCancelToken = axios.CancelToken;
varsource = 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.');
当然,无论选择哪一种方式都需要自身结合业务的需要和自我的认知,没有哪个绝对的优秀,也没有哪个绝对不优秀。
SegmentFault 思否社区和文章作者展开更多互动和交流。返回搜狐,查看更多