本文共 7295 字,大约阅读时间需要 24 分钟。
上古浏览器页面在向服务器请求数据时,因为返回的是整个页面的数据,页面都会强制刷新一下,这对于用户来讲并不是很友好。并且我们只是需要修改页面的部分数据,但是从服务器端发送的却是整个页面的数据,十分消耗网络资源。而我们只是需要修改页面的部分数据,也希望不刷新页面,因此异步网络请求就应运而生。
Ajax(Asynchronous JavaScript and XML):异步网络请求。Ajax能够让页面无刷新的请求数据。
实现ajax的方式有多种,如jQuery封装的ajax,原生的XMLHttpRequest,以及axios。但各种方式都有利弊
- 原生的XMLHttpRequest的配置和调用方式都很繁琐,实现异步请求十分麻烦
- jQuery的ajax相对于原生的ajax是非常好用的,但是没有必要因为要用ajax异步网络请求而引用jQuery框架
Axios,可以理解为ajax i/o system,这不是一种新技术,本质上还是对原生XMLHttpRequest的封装,可用于浏览器和nodejs的HTTP客户端,只不过它是基于Promise的,符合最新的ES规范。具备以下特点:
- 在浏览器中创建XMLHttpRequest请求
- 在node.js中发送http请求
- 支持Promise API
- 拦截请求和响应
- 转换请求和响应数据
- 取消要求
- 自动转换JSON数据
- 客户端支持防止CSRF/XSRF(跨域请求伪造)
原生XMLHttpRequest实现ajax请求
var request = new XMLHttpRequest(); // 创建XMLHttpRequest对象//ajax是异步的,设置回调函数request.onreadystatechange = function () {      // 状态发生变化时,函数被回调    if (request.readyState === 4) {      // 成功完成        // 判断响应状态码        if (request.status === 200) {                 // 成功,通过responseText拿到响应的文本:            return success(request.responseText);        } else {                 // 失败,根据响应码判断失败原因:            return fail(request.status);        }    } else {             // HTTP请求还在继续...    }}// 发送请求:request.open('GET', '/api/categories');request.setRequestHeader("Content-Type", "application/json") //设置请求头request.send();//到这一步,请求才正式发出     axios是基于Promise的,因此可以使用Promise API
axios的请求方式:
- axios(config)
- axios.request(config)
- axios.get(url [,config])
- axios.post(url [,data [,config]])
- axios.put(url [,data [,config]])
- axios.delete(url [,config])
- axios.patch(url [,data [,config]])
- axios.head(url [,config])
//执行GET请求import axios from 'axios'axios.default.baseURL = 'http://localhost:3000/api/products'axios.get('/user?ID=12345')  //返回的是一个Promise    .then(res=>console.log(res))    .catch(err=>console.log(err));    //可配置参数的方式
axios.get(’/user’,{ params:{ ID:12345 } }).then(res=>console.log(res)) .catch(err=>console.log(err));//发送post请求axios.post('/user',{       firstName: 'simon',    lastName:'li'}).then(res=>console.log(res))    .catch(err=>console.log(err));     通过axios.all(iterable)可实现发送多个请求,参数不一定是数组,只要有iterable接口就行,函数返回的是一个数组
axios.spread(callback)可用于将结果数组展开
//发送多个请求(并发请求),类似于promise.all,若一个请求出错,那就会停止请求const get1 = axios.get('/user/12345');const get2 = axios.get('/user/12345/permission');axios.all([get1,get2])    .then(axios.spread((res1,res2)=>{       	console.log(res1,res2);	}))    .catch(err=>console.log(err))   axios(config)可通过设置一些属性来发送请求
//发送post请求axios({       method: 'post',  //请求方式,默认是get请求    url:'/user/12345', //地址    data:{    //参数        firstName: 'simon',        lastName: 'li'    }});   可用axios,create([config])来创建一个新的实例,并设置相关属性
const instance = axios.create({       baseURL: 'http://localhost:3000/api/products',    timeout: 1000,    headers: {   'X-Custom-Header':'foobar'}});//instance的使用instance.get('/user',{       params:{   ID:12345}}).then(res=>console.log(res)).catch(err=>console.log(err))   {       //服务器的地址,是必须的选项    url: '/user', //请求的方式,若没有则默认是getmethod:'get',    //如果url不是绝对地址,则会加上baseURLbaseURL: 'http://localhost:3000/',   //transformRequest允许请求的数据在发送至服务器之前进行处理,这个属性只适用于put、post、patch方式//数组的最后一个函数必须返回一个字符串或者一个'ArrayBuffer'或'Stream'或'Buffer' 实例或'ArrayBuffer','Formdata',//若函数中用到了headers,则需要设置headers属性    transformRequest: [function(data,headers){        //根据需求对数据进行处理    return data;}],    //transformResponse允许对返回的数据传入then/catch之前进行处理    transformResponse:[function(data){        //依需要对数据进行处理    return data;}],   //headers是自定义的要被发送的信息头headers: {    'X-Requested-with':'XMLHttpRequest'},    //params是请求连接中的请求参数,必须是一个纯对象params:{      ID:12345  },    //paramsSerializer用于序列化参数paramsSerializer: function(params){      return Qs.stringify(params,{    arrayFormat:'brackets'});  },     //data是请求时作为请求体的数据——request.body//只适用于put、post、patch请求方法//浏览器:FormData,File,Blob;Node:streamdata:{      firstName: 'simon',  },    //timeout定义请求的时间,单位是毫秒,如果请求时间超过设定时间,请求将停止timeout:1000,    //withCredentials表明跨跨域请求书否需要证明。withCredentials:false, //默认值    //adapter适配器,允许自定义处理请求//返回一个promiseadapter:function(config){        /*...*/},     //auth表明HTTP基础的认证应该被使用,并提供证书auth:{      username:'simon',  password:'123456',    },    //responseType表明服务器返回的数据类型,这些类型包括:json/blob/document/ 		arraybuffer/text/stream     responseType: 'json',         //proxy定义服务器的主机名和端口号 //auth属性表明HTTP基本认证应该跟proxy相连接,并提供证书 //这将设置一个'Proxy-Authorization'头(header),覆盖原来自定义的 proxy:{         host:127.0.0.1,     port:8080,     auth:{             username:'simon',         password:'123456'         }     },     //取消请求 cancelToken: new CancelToken(cancel=>{    })  }
可以给axios或者axios实例添加默认设置,这样当使用时将默认带上相应的信息,避免每次请求都重复操作
全局默认设置是指给axios添加一些默认设置,如baseURL等,后面发送请求时,所有请求都会带上这些设置
import axios from 'axios'axios.default.baseURL = 'http://localhost/api/';axios.default.headers.common['Authorization'] = AUTH_TOKEN; 1 2 3
也可以先实例化一个axios,再给这个实例添加一些默认设置,实例去发送请求时便会带上这些设置,但不会影响其他的实例或全局axios
const instance = axios.create({         //创建实例时就进行默认设置    baseURL: 'http://localhost:3000/api',});//在实例外进行默认设置instance.default.headers.common['Authorization'] = AUTH_TOKEN;              1     2     3     4     5     6 设置是可以被覆盖的,设置包括了全局默认设置,实例默认设置以及请求中config中的默认设置,越往后,优先级越高,后面的会覆盖前面的设置
import axios from 'axios'axios.default.timeout = 1000; //全局默认设置const instance = axios.create({         timeout: 2000,  //实例默认设置});//请求时的默认设置instance.get('/users/123456',{         timeout: 3000,  //最后这个设定的时间会生效}).then(/*....*/).catch(/*....*/) 一个请求的返回(即响应)包含以下信息
{         //data是服务器提供的响应    data:{     }, //服务器返回的http状态码   status: 200, //statusText是服务器返回的http状态信息statusText: 'ok',    //heades是服务器响应中携带的headersheaders:{      },//config是axios进行的设置,目的是为了请求(request)config:{      },}
//使用then后,response中将包含上述信息
axios.get(’/user/12345’).then(response={ console.log(response.data); console.log(response.status); console.log(response.statusText); console.log(response.headers); console.log(response.config); })拦截器是指当发送请求或者得到响应被then或catch处理之前对它们进行拦截,拦截后可对数据做一些处理,比如给请求数据添加头部信息,或对响应数据进行序列化,然后再传给浏览器,这些都可以在拦截器中进行
//添加一个请求拦截器axios.interceptors.request.use(config=>{       //在请求之前做一些事    return config;},err=>{      //请求错误的时候做一些事    return Promise.reject(err);});  //添加一个响应拦截器
axios.interceptors.response.use(response=>{ //对返回的数据做一些处理 reutrn response; },err=>{ //对返回的错误做一些处理 return Promise.reject(err); });//移除拦截器const myInterceptor = axios.interceptors.request.use(config=>{   return cofig})axios.interceptors.request.eject(myInterceptor);  //在一个axios实例中使用拦截器
var instance = axios.create(); instance.interceptors.request.use(function(){ /…/});在请求拦截中,错误拦截较少,通常都是配置相关的拦截
在响应拦截中,若成功,则主要是对数据进行过滤;若失败,则可以根据starus判断报错的状态码,来跳转到不同的错误提示页面
使用
validateStatus设置选项自定义HTTP状态码的错误范围
axios.get('user/12345',{       validateStatus:function(status){           return status < 500;//当返回码小于等于500时视为错误    }});  ">取消请求         可以使用cancel token取消一个请求,当用户搜索时,可能需要频繁的发送数据查询请求,因此当发送下一个请求时 ,需要撤销上一个请求。因此需要取消请求。     const CancelToken = axios.CancelToken;//使用CancelToken.source工厂函数创建一个cancel tokenconst source = CancelToken.source();  axios.get(’/user/12345’,{
cancelToken: source.toke }).catch(thrown=>{ if(axios.isCancel(thrown)){ console.log(‘Request canceled’, thrown.message); }else{ //handle error } });//取消请求
source.cancel(‘操作被用户取消’);参考链接: http://www.axios-js.com/docs/index.html
转载地址:http://uyrmz.baihongyu.com/