vue实践---vue结合 promise 封装原生ajax

时间:2021-02-08 06:55:19

有时候不想使用axios这样的外部依赖,想自己封装ajax,这里有两种方法

方法一,在单个页面内使用

封装的代码如下:

 beforeCreate () {
this.$http = (() => {
let createFetch = (type, url, params) => {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
if (xhr.readyState === 4){
if(xhr.status === 200){
var res = xhr.responseText;
try {
res = JSON.parse(xhr.responseText)
} catch (e) {}
resolve(res)
} else {
reject(xhr.responseText)
}
}
}
url += url.includes('?') ? '&' : '?' if (type === 'GET') {
let serialArr = []
Object.keys(params).forEach(v => {
serialArr.push(`${v}=${params[v]}`)
})
url += serialArr.join('&')
}
xhr.withCredentials = true; //支持跨域发送cookies
xhr.open(type, url, true);
xhr.send(type === 'GET' ? null : params);
})
}
return {
get: (...args) => createFetch("GET", args[0], args[1]),
post: (...args) => createFetch("POST", args[0], args[1])
}
})()
}

使用的代码如下:

this.$http.get('http://123.103.9.204:6058/official/rest/document/wenku/1/3293036/groupList', {pageSize: '1', pageSize: 30, groupType: 0}).then((res)=>{
if(res.flag == 0){
this.requestData = res.data
}
})

方法二,全局注册

封装的方法如下:

export default
{
install(Vue)
{
Vue.prototype.$http=function(options){
/*将数据转化为字符串*/
var strData=function(data){
var dataStr="";
for(var key in data){
dataStr += key+'='+data[key]+'&';
}
dataStr = dataStr && dataStr.slice(0,-1);
return dataStr;
};
/*创建 XMLHttpRequest 对象*/
var createXHR=function(){
var xhr;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xhr=new XMLHttpRequest();
}
else {// code for IE6, IE5
xhr=new ActiveXObject("Microsoft.XMLHTTP");
}
return xhr
};
/*向服务器发送请求*/
var open=function(xhr,type,url,async){
xhr.open(type,url,async);
};
var send=function(xhr,msg){
xhr.send(msg);
};
var setHeaders=function(xhr,headers){
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
if(!headers){
return false;
}
for(var key in headers){
xhr.setRequestHeader(key,headers[key]);
}
}
var request=function(xhr,opts){
if(opts.type==="GET"){
open(xhr,opts.type,opts.url+'?'+strData(opts.data),opts.async);
send(xhr,null);
}
else if(opts.type==="POST"){
open(xhr,opts.type,opts.url,opts.async);
if(opts.headers){
setHeaders(xhr,opts.headers);
}
send(xhr,strData(opts.data));
}
};
return new Promise((resolve,reject)=>{
if(!options || typeof options != 'object'){
reject(new Error("参数错误,请传入对象参数!"));
return false;
}
if(!options.url){
reject(new Error("url不能为空"));
return false;
}
options.type = options.type?options.type.toUpperCase():'GET';
options.async = (options.async && options.async === false)?false:true;
options.dataType = options.dataType || "json";
options.data = options.data || {};
options.headers = options.headers || {};
var dataStr=strData(options.data);
/*创建 XMLHttpRequest 对象*/
var xhr=createXHR();
/*创建服务器返回响应后执行操作函数*/
xhr.onreadystatechange=function(){
var responseData;
if(xhr.readyState == 4){
switch (xhr.status){
case 200:
switch (options.dataType){
case "xml":
responseData=xhr.responseXML;
break;
case "text":
responseData = xhr.responseText;
break;
case "json":
responseData = JSON.parse(xhr.responseText);
break;
}
resolve(responseData);
default:
reject(new Error("这里做错误处理"));
}
}
};
/*向服务器发送请求*/
request(xhr,options);
})
};
Vue.prototype.$post=function(options){
options.type='post';
return this.$http(options);
};
Vue.prototype.$get=function(options){
options.type='get';
return this.$http(options);
};
}
}
import Vue from 'vue'
import App from './App.vue'
import router from './router' import Install from './install/index.js'
// 这里全局安装
Vue.use(Install) new Vue({
el: '#app',
router,
render: h => h(App)
})

使用的代码如下:

            var reuestData = {
url: "http://123.103.9.204:6058/official/rest/document/wenku/1/3293036/groupList",
data: {pageSize: '1', pageSize: 30, groupType: 0}
}
this.$get(reuestData).then((res)=>{
if(res.flag == 0) {
this.requestData = res.data
}
})

两种方法的比较:

方法一的每个页面要想使用, 都需要写相关的代码,而且由于使用了匿名函数立即执行,如果函数内部有错误,不好调试

方法二使用了全局注册,只要在main.js 注册了全局都可以使用。

具体的代码可以看这里:https://github.com/YalongYan/vue-practice/tree/master/vue-native-ajax

vue实践系列请看这里:https://github.com/YalongYan/vue-practice