axios的使用、fetch和XMLHttpRequest请求封装

axios的使用

安装axios

npm install axios --save
bower install axios --save

引用
直接script标签引用

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

ES6 import引用
因为axios不是vue的插件,所以不能直接用use方法,需要将其加载到原型上。

import axios from 'axios'
axios.get();

如果要全局使用axios就需要在main.js中设置成全局的,然后再组件中通过this调用

Vue.prototype.$axios = axios;

this.$axios.get();

使用
发送一个最简单的请求
这里我们发送一个带参数的get请求,params参数放在get方法的第二个参数中,如果没有参数get方法里可以只写路径。如果请求失败捕获一下异常。

axios
  .get('http://rap2api.taobao.org/app/mock/23080/resources/search',{
      params: {
         id: 5
      }
   })
  .then(res => {
    console.log('数据是:', res);
  })
  .catch((e) => {
    console.log('获取数据失败');
  });

当然,我们也可以发送一个POST请求,post方法的第二个参数为请求参数对象。

this.$axios.post('http://rap2api.taobao.org/app/mock/121145/post',{
  name: '小月'
})
.then(function(res){
  console.log(res);
})
.catch(function(err){
  console.log(err);
});

一次合并发送多个请求
分别写两个请求函数,利用axios的all方法接收一个由每个请求函数组成的数组,可以一次性发送多个请求,如果全部请求成功,在axios.spread方法接收一个回调函数,该函数的参数就是每个请求返回的结果。

function getUserAccount(){
  return axios.get('/user/12345');
}
function getUserPermissions(){
  return axios.get('/user/12345/permissions');
}
this.$axios.all([getUserAccount(),getUserPermissions()])
  .then(axios.spread(function(res1,res2){
    //当这两个请求都完成的时候会触发这个函数,两个参数分别代表返回的结果
}))

axios的API
以上通过axios直接调用发放来发起对应的请求其实是axios为了方便起见给不同的请求提供的别名方法。我们完全可以通过调用axios的API,传递一个配置对象来发起请求。

发送post请求,参数写在data属性中

axios({
  url: 'http://rap2api.taobao.org/app/mock/121145/post',
  method: 'post',
  data: {
    name: '小月'
  }
}).then(res => {
  console.log('请求结果:', res);
});

发送get请求,默认就是get请求,直接第一个参数写路径,第二个参数写配置对象,参数通过params属性设置。

axios('http://rap2api.taobao.org/app/mock/121145/get', {
  params: {
    name: '小月'
  }
}).then(res => {
  console.log('请求结果:', res);
});

axios为所有请求方式都提供了别名:

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])

axios配置默认值
1、可以通过axios.defaults设置全局默认值,在所有请求中都生效。

axios.defaults.headers.common["token"] = ""
axios.defaults.headers.post["Content-type"] = "application/json"
axios.defaults.baseURL = 'https://service.xxx.com; //设置统一路径前缀

2、也可以自定义实例的默认值,以及修改实例的配置

// 创建时自定义默认配置,超时设置为全局默认值0秒
let ax = axios.create({
  baseURL: 'http://rap2api.taobao.org',
  params: { name: '小月' }
});
// 修改配置后,超时设置为4秒
ax.defaults.timeout = 4000; 

3、也可以像前面那样,在每个请求中设置相关的配置。

axios('/app/mock/121145/get', {
  params: {
    name: 'xiaoxiao'
  },
  baseURL: 'http://rap2api.taobao.org'
})

以上配置方法优先级从1-3依次增高,更多配置选项查看文档。

{
    method:'请求方法',
    baseURL:'如果路径不是绝对路径,就会在路径前自动添加此路径',
    transformRequest: [(data, header)=>{}], //在发送请求之前修改数据,适用于post、put、patch
    transformResponse:  [(data)=>{
        return JSON.parse(data).data;
    }], //在收到的数据传到then之前修改数据,注意这里data是个字符串类型。
    header: {'X-Requested-With': 'XMLHttpRequest'}, //请求头
    params: {}, //请求参数
    paramsSerializer: (params)=>{
        return qs.stringify(params); //name=xiaohong&id=1
    } //可选函数,可以把参数拼接成字符串
    data: {}, // post类方法的请求体参数
    timeout: 0, //请求延时事件,如果超时请求终止
    withCredentials: false, //是否时跨站点请求
    onUploadProgress: (progressEvent)=>{
        //可以通过progressEvent拿到上传的进度
    },
    onDownloadProgress: ()=>{},//和onUploadProgress一样,获取下载的进度
    responseType: json,  // 返回的数据格式
    maxContentLength: 2000, //相应内容的最大尺寸
    validateStatus: (validateStatus)=>{
        return validateStatus >= 200; //限制相应状态码,如果不满足就拒绝
    },
    cancelToken: new cancelToken(function(cancel){}) // 指定一个取消请求标识,下面会用到
}

拦截器
可以分别设置请求拦截和响应拦截,在发出请求和响应到达then之前进行判断处理。

axios.interceptors.response.use(
  res => {
    if (res) {
      return res;
    }
  },
  err => {
    return Promise.reject(error);
  }
);

以上以相应拦截器为例,请求拦截器同样,只是把response换成request。第一个参数是成功回调,第二个是错误回调。
也可以移除拦截器,就像移除js定时器一样的操作:

var myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);

取消请求
1、取消请求的话需要先通过创建一个CancelToken.source工厂函数创建一个标识source
2、通过配置项制定标识,这样才知道取消的是哪个请求
3、调用取消方法

var CancelToken = axios.CancelToken;
var source = CancelToken.source(); //1
axios.post('/user/12345', {
  name: 'new name'
}, {
  cancelToken: source.token //2
})
source.cancel('Operation canceled by the user.'); //3

还有一种写法是直接把cancelToken的构造函数传递给配置项,该构造函数接受一个函数作为参数,在这个函数中指定标识符。

var CancelToken = axios.CancelToken;
var cancel;
axios.get('/app/mock/121145/get', {
  baseURL: 'http://rap2api.taobao.org',
  cancelToken: new CancelToken(function executor(c) {
    cancel = c;
  })
});
cancel();

跨域配置
如果我们要跨域请求数据,在配置文件里设置代理,vue-cli3项目,需要在根目录自己创建一个vue.config.js,在里面写配置。

module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'https://www.xxx.com', //目标路径,别忘了加http和端口号
        changeOrigin: true, //是否跨域
        ws: true,
        pathRewrite: {
          '^/api': '' //重写路径
        }
      }
    }
  }
};

调用接口:

axios.post('/api/test', {name: 'xiao'}); 

如果没有重写路径,访问的就是https://www.xxx.com/api/test,如果像上面代码那样重写路径访问的就是https://www.xxx.com/test。

原理:
因为客户端请求服务端的数据是存在跨域问题的,而服务器和服务器之间可以相互请求数据,是没有跨域的概念(如果服务器没有设置禁止跨域的权限问题),也就是说,我们可以配置一个代理的服务器可以请求另一个服务器中的数据,然后把请求出来的数据返回到我们的代理服务器中,代理服务器再返回数据给我们的客户端,这样我们就可以实现跨域访问数据啦。

fetch和XMLHttpRequest请求封装

import { baseUrl } from './env'

export default async(url = '', data = {}, type = 'GET', method = 'fetch') => {
	type = type.toUpperCase();
	url = baseUrl + url;

	if (type == 'GET') {
		let dataStr = ''; //数据拼接字符串
		Object.keys(data).forEach(key => {
			dataStr += key + '=' + data[key] + '&';
		})

		if (dataStr !== '') {
			dataStr = dataStr.substr(0, dataStr.lastIndexOf('&'));
			url = url + '?' + dataStr;
		}
	}

	if (window.fetch && method == 'fetch') {
		let requestConfig = {
			credentials: 'include',
			method: type,
			headers: {
				'Accept': 'application/json',
				'Content-Type': 'application/json'
			},
			mode: "cors",
			cache: "force-cache"
		}

		if (type == 'POST') {
			Object.defineProperty(requestConfig, 'body', {
				value: JSON.stringify(data)
			})
		}
		
		try {
			const response = await fetch(url, requestConfig);
			const responseJson = await response.json();
			return responseJson
		} catch (error) {
			throw new Error(error)
		}
	} else {
		return new Promise((resolve, reject) => {
			let requestObj;
			if (window.XMLHttpRequest) {
				requestObj = new XMLHttpRequest();
			} else {
				requestObj = new ActiveXObject;
			}

			let sendData = '';
			if (type == 'POST') {
				sendData = JSON.stringify(data);
			}

			requestObj.open(type, url, true);
			requestObj.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			requestObj.send(sendData);

			requestObj.onreadystatechange = () => {
				if (requestObj.readyState == 4 && requestObj.status == 200) {
						let obj = requestObj.response
						if (typeof obj !== 'object') {
							obj = JSON.parse(obj);
							}
						resolve(obj)
					} else {
						reject(requestObj)
					}
				}
			}
		})
	}
}

使用:

export const getcaptchas = () => fetch('/v1/captchas', {},'POST');
export const currentcity = number => fetch('/v1/cities/' + number);

你可能感兴趣的:(前端开发,vue,ajax,js)