原生ajax简易封装
a.js //通过封装成一个js文件并暴露出去 //使用多个实参必须按照顺序进行传递而且还不能传空,所以采用了options配置对象,就是设置一个形参, //传递一个对象成为一个实参 export default function ajax(options={}){ //合并第一个参数并重新赋值给options,如果options里面有值则会替换掉第一个对象里面的值 options=Object.assign({ url:'', method:'get', data:null, //因为采用了promise所以注释了 //sucess:null },options); //引入qs.js库进行处理数据 options.data=qs.stringify(options.data); //判断是否是get请求,如果是get请求就把data里面数据转换成键值对字符串拼接 let isGET=/^(GET|DELETE|HEAD|OPTIONS)$/.test(options.method); //如果是get请求且数据存在则进行处理 if(isGET&&options.data){ //判断路径是否存在问号并拼接数据 options.url+=`${option.url.includes('?')?'&':'?'}${options.data}`; //把data设置为空 options.data=null; } //通过promise把当前封装的ajax改成异步 return new Promise((resolve,reject)=>{ //创建ajax对象 let xhr= new XMLHttpRequest; //请求前的准备,设置请求方式和请求地址 xhr.open(options.method,options.url); //监听请求发送和状态码返回 xhr.onreadystatechange=function(){ //不等于200返回服务器的报错信息 if(!/^2\d{2}$/.test(xhr.status)){ reject(xhr); return; } //判断状态码是否为200和是否请求装态码是否为4 if(/^2\d{2}$/.test(xhr.status)&&xhr.readyState===4){ //成功从服务器获取结果,服务器返回时json字符串所以要转成json对象 //判断success是否传递为函数为函数则执行不为则取消 //typeof options.success=== 'function'?options.success(JSON.parse(xhr.responseText)):null; //进阶 请求成功且状态码为2xx的时候则返回数据 resolve(JSON.parse(xhr.responseText)); } }; //如果不是get请求则通过发送请求体进行传递参数,send发送请求必须写到最后面 xhr.send(options.data) }) }
调用封装的ajax
b.js import ajax form './a.js'; ajax({ url:'请求地址', method:'get', data:{}, success:function(res){ console.log(res) } })
封装ajax点方法
['get','psot','delete','put','head','options'].forEach(item=>{ ajax[item]=function(url='',data={}){ return ajax( { url, method:item, data } ) } }) //导出 export default ajax;
调用点方法
function getUser(){ return ajax.get('URL') }
ajax串行
getUser().then(res=>{ return getpost() })
异步中的同步
async await async 定义异步函数 await 那些操作异步执行 ( async function(){ let result =await getUser(); result=await getpost(); result=await getput(); } )();
基于axios二次封装
//引入axios import axios form 'axios'; //引入qs import qs form 'qs'; //设置请求接口前缀 axios.defaults.baseURL='http://127.0.0.1:8000'; //设置传给服务器设置统一格式 axios.defaults.headers['Content-Type']='application/x-www-form-urlencoded'; //通过qs转换成json字符串格式传给服务器 axios.defaults.transformRequest=data=>qs.stringify(data); //设置超时时间 axios.defaults.timeout=0; //在跨域请求时,会携带用户凭证 //前端配置了withCredentials=true,后段设置Access-Control-Allow-Origin不能为 " * ",必须是你的源地址 axios.defaults.withCredentials=true; //请求拦截器 axios.interceptors.request.use(config=>{ //登录成功后,把从服务器获取的token信息存储到本地,以后在发请求,直接把token带上(自定义请求携带),服务器拿到token进行令牌效验,查看请求是否合法 let token =localStorage.getItem('token'); token&&(config.headers['Authorization']=token); return config; }) //响应拦截器 //从服务器获取结果到自己.then中间做的事 axios.interceptors.response.use(response=>{ //从服务器获取到数据,只把响应主题信息传给下一个then return response.data; },reason=>{ //服务器没有获取数据(网络层失败) let response =null; if(reason){ //服务器有响应,状态码是4/5开头的 response=reason.response; //跟据状态码做出响应 switch(response.status){ case 401: //一般情况401是未登录 break; case 403: //一般情况下是token过期 break; case 404: //地址不存在 break; } }else{ if(!window.navigator.onLine){ alert('网络已断开,请联网在试!!!') } } return Promise.reject(response); }) //把处理好的axios暴露出去,让其他页面可以引用和使用 export default axios;
使用二次封装的axios
//发送请求 axios.get('/job',{ data });
fetch
fetch是浏览器内置函数,基于fetch可以像服务器发送请求,核心原理和ajax不一致(天生就是基于promise管理的) 终极方案,不论服务器返回的状态码是多少,都按照promise成功算,只有断网,才算失败
fetch('url').then(res=>{ //json是fetch的方法 return res.json() }).then(res=>{ //这个才是结果 console.log(res) })
fetch封装拦截器
import qs form 'qs'; //设置请求前缀 let baseURL ='http://127.0.0.1:3000'; //暴露出去 第一个参数是路径 第二个是配置对象 export default function request(url,options={}){ url=baseURL+url; //get系列请求处理 如果请求未填写默认get !options.method?options.method='GET':null; if(options.hasOwnProperty('params')){ //匹配这些字符 i忽略大小写 if(/^(GET|DELETE|HEAD|OPTIONS)$/i.test(options.method)){ const ask=url.includes('?')?'&':'?'; url+=`$ask${qs.stringify(params)}`; } delete options.params; } //合并配置项 options=OBject.assign({ //允许跨域携带资源凭证 same-origin同源可以 omit都拒绝 credentials:'include', //设置请求头 headers:{} },options); options.headers.Accept='application/json'; //token效验 const token localStorage.getItem('token'); token&&(options.headers.Authorization=token); //post请求 if(/(^POST|PUT)$/i.test(options.method)){ !options.type?options.type='urlencoded':null; if(options.type=== 'urlencoded'){ options.headers['Content-Type']='application/x-www-form-urlencoded'; options.body=qs.stringify(options.body); } } //拦截器 return fetch(url,options).then(response=>{ //返回的结果可能是非200状态 if(!/^(2|3)\d{2}$/.test(response.status)){ switch(response.status){ case 401: break; case 403: break; case 404: break; } return Promise.reject(response); } return response,json(); }).catch(error=>{ if(!window.navigator.onLine){ //断开网络了,可以跳转到其他页面 return; } return Promise.reject(error); }) }
跨域
跨域产生的原因和意义
//项目过大会进行服务器分离并进行高并发处理,如web服务器,图片服务器,数据服务器 云信息共享api:第三方api接口 有助于分离开发:开发跨域,部署同源 解决 修改本地host jsonp cors proxy
第一种方案:通过修改本地的HOST进行请求,可以进行DNS处理,DNS处理就是设置俩个地址,如果本地的DNS访问不到 就访问网络的DNS 属于骗过浏览器 需要访问把你访问的地址映射到你现在的ip 类似于反向代理 第二种方案:jsonp 第一:jsonp需要服务器支持 第二:由于script本身就是下载资源的,所有只能采用get请求 安全系数低 第三种:cors 服务端设置cors之后不能携带cookie 要不只设置一个源,这个一个源可以携带cookie
Vue和react都是基于webpack,webpack里面的webpack-dev-sever能起一个web服务,Web服务中支持跨域处理 ,叫proxy(跨域资源处理),跨域请求代理 需要在webpack.config.js里面的devServer加一个proxy属性 proxy:{ //拦截开头带/的请求,代理到target属性中 '/':{ target:"http://127.0.0.1:3000", changeOrigin:true } } 发送请求,前面什么都不加就是向自己发送请求,整个web服务都是dev-server帮我们启的,然后在proxy里面 的/属性代理到发送请求的地址 fetch('/user')