原生ajax请求

一、手写AJAX的步骤

node 运行npm install jquery -s安装-s创建和发布都要用dependencies -d只在创建使用上线后不用

  1. 创建XMLHttpRequest对象
  2. 指定响应函数
  3. 打开连接(指定请求)
  4. 发送请求
  5. 创建响应函数

注:第三步是使用XMLHttpRequest对象的open()方法,字面意思open是打开的意思,即打开连接。但是准确的说应该是指定Http请求。因为浏览器在使用AJAX技术与服务通信时,发送的是Http请求,那么就要指定Http的请求方法,url等信息。

var xmlhttp=null;//声明一个变量,用来实例化XMLHttpRequest对象
if (window.XMLHttpRequest)
  {
  xmlhttp=new XMLHttpRequest();// 新版本的浏览器可以直接创建XMLHttpRequest对象
  }
  
else if (window.ActiveXObject)
  {
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");// IE5或IE6没有XMLHttpRequest对象,而是用的ActiveXObject对象
  }
  
  
if (xmlhttp!=null)
  {
  xmlhttp.onreadystatechange=state_Change;//指定响应函数为state_Change
  xmlhttp.open("GET","/example/xdom/note.xml",true);//指定请求,这里要访问在/example/xdom路径下的note.xml文件,true代表的使用的是异步请求
  xmlhttp.send(null);//发送请求
  } 
else
  {
  alert("Your browser does not support XMLHTTP.");
  }

//创建具体的响应函数state_Change
function state_Change()
{
if (xmlhttp.readyState==4)
  {
  if (xmlhttp.status==200)
    {
    // 这里应该是函数具体的逻辑
    }
  else
    {
    alert("Problem retrieving XML data");
    }
  }
}

二、promise封装ajax

            //创建promise对象
            const p = new Promise((resolve, reject) => {
                //创建XMLHttpRequest对象
                const xhr = new XMLHttpRequest;
                //初始化
                xhr.open('GET', 'http://127.0.0.1/api/get');
                //发送
                xhr.send();
                //处理响应信息
                xhr.onreadystatechange = function () {
                    //0	UNSENT	代理被创建,但尚未调用 open() 方法。
                    // 1	OPENED	open()方法已经被调用。
                    // 2	HEADERS_RECEIVED	send()方法已经被调用,并且头部和状态已经可获得。
                    // 3	LOADING	下载中; 属性已经包含部分数据。responseText
                    // 4	DONE	下载操作已完成。 
                    if (xhr.readyState == 4) {
                        if (xhr.status >= 200 && xhr.status < 300) {
                            //输出响应成功的结果
                            resolve("响应" + xhr.response);
                        }
                        else {
                            reject(xhr.status);
                        }
                    }
                }
            })
            p.then(value => {
                console.log(value);
            }, reason => {
                console.log(reason);
            })

三、vue封装axios

  • 1.在src目录下创建文件夹并命名api
    2.将文件夹的下面创建一个js文件命名为axios
  • 3.封装请求/响应拦截器(instance)axios实例
//使用自定义配置的文件发送请求
const instance = axios.create({
    baseURL: '',
    timeout: 8000,
    headers:{
        
    }
})
//添加请求拦截器
instance.interceptors.request.use(function (config){
    return config
},function (error){
    return  Promise.reject(error)
})

//添加响应拦截器
instance.interceptors.response.use(function (response){
    instance
    if(response.status === 200){
        return response
    }else{
        console.error('请求错误')
        console.error(response)
    }
    return response
},function (error){
    return Promise.reject(error)
})

export default instance

  • 4.接着创建一个js文件名为http,将我们封装后的axios导入
import http from './axios'
  • 5.封装函数
function getList(type,pageNum,pageSize){
    let url = new URLSearchParams()
    url.append('type',type)
    url.append('pageNum',pageNum)
    url.append('pageSize',pageSize)
    return http.post('/api/weChat/applet/course/list/type',url)
}
//导出
export {getList}

  • 6.在需要请求的页面导入该函数
import {getList} from "@/api/http";
  • 7.在created生命周期中进行请求
getList(this.type,this.pageNum,this.pageSize).then(res=>{
      console.log(res.data.rows)
      this.msg = res.data.rows
      this.flag2 = false
})
  • 8.配置跨域代理
//配置跨域
module.exports = {
    lintOnSave: false,//取消严格模式
    devServer: {
        // 设置主机地址
        host: 'localhost',
        // 设置默认端口
        port: 8080,
        // 设置代理
        proxy: {
            '/api': {
                // 目标 API 地址
                target: 'http://127.0.0.1:3000/',
                // 如果要代理 websockets
                ws: false,
                // 将主机标头的原点更改为目标URL
                changeOrigin: true,
                pathRewrite: {
                    // 路径重写
                    "/api": "" // 这个意思就是以api开头的,定向到哪里, 如果你的后边还有路径的话, 会自动拼接上
                }
            }
        }
    }
}

请求拦截

 // 先导入vuex,因为我们要使用到里面的状态对象
// vuex的路径根据自己的路径去写
import store from '@/store/index';

// 请求拦截器axios.interceptors.request.use(    
    config => {        
        // 每次发送请求之前判断vuex中是否存在token        
        // 如果存在,则统一在http请求的header都加上token,这样后台根据token判断你的登录情况
        // 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断 
        const token = store.state.token;        
        token && (config.headers.Authorization = token);        
        return config;    
    },    
    error => {        
        return Promise.error(error);    
})

一般是在登录完成之后,将用户的token通过localStorage或者cookie存在本地,然后用户每次在进入页面的时候(即在main.js中),会首先从本地存储中读取token,如果token存在说明用户已经登陆过,则更新vuex中的token状态。然后,在每次请求接口的时候,都会在请求的header中携带token,后台人员就可以根据你携带的token来判断你的登录是否过期,如果没有携带,则说明没有登录过。每个请求都携带token,那么要是一个页面不需要用户登录就可以访问的怎么办呢?其实,你前端的请求可以携带token,但是后台可以选择不接收啊!

响应拦截

 // 响应拦截器
axios.interceptors.response.use(    
    response => {   
        // 如果返回的状态码为200,说明接口请求成功,可以正常拿到数据     
        // 否则的话抛出错误
        if (response.status === 200) {            
            return Promise.resolve(response);        
        } else {            
            return Promise.reject(response);        
        }    
    },    
    // 服务器状态码不是2开头的的情况
    // 这里可以跟你们的后台开发人员协商好统一的错误状态码    
    // 然后根据返回的状态码进行一些操作,例如登录过期提示,错误提示等等
    // 下面列举几个常见的操作,其他需求可自行扩展
    
    error => {            
        if (error.response.status) {            
            switch (error.response.status) {                
                // 401: 未登录
                // 未登录则跳转登录页面,并携带当前页面的路径
                // 在登录成功后返回当前页面,这一步需要在登录页操作。                
                case 401:                    
                    router.replace({                        
                        path: '/login',                        
                        query: { 
                            redirect: router.currentRoute.fullPath 
                        }
                    });
                    break;
                // 403 token过期
                // 登录过期对用户进行提示
                // 清除本地token和清空vuex中token对象
                // 跳转登录页面                
                case 403:
                     Toast({
                        message: '登录过期,请重新登录',
                        duration: 1000,
                        forbidClick: true
                    });
                    // 清除token
                    localStorage.removeItem('token');
                    store.commit('loginSuccess', null);
                    // 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面 
                    setTimeout(() => {                        
                        router.replace({                            
                            path: '/login',                            
                            query: { 
                                redirect: router.currentRoute.fullPath 
                            }                        
                        });                    
                    }, 1000);                    
                    break; 
                // 404请求不存在
                case 404:
                    Toast({
                        message: '网络请求不存在',
                        duration: 1500,
                        forbidClick: true
                    });
                    break;
                // 其他错误,直接抛出错误提示
                default:
                    Toast({
                        message: error.response.data.message,
                        duration: 1500,
                        forbidClick: true
                    });
            }
            return Promise.reject(error.response);
        }
    } 
});
//上面的Toast()方法,是我引入的vant库中的toast轻提示组件,你根据你的ui库,对应使用你的一个提示组件。
axios发送请求
/**
 * get方法,对应get请求
 * @param {String} url [请求的url地址]
 * @param {Object} params [请求时携带的参数]
 */
export function get(url, params){    
    return new Promise((resolve, reject) =>{        
        axios.get(url, {            
            params: params        
        }).then(res => {
            resolve(res.data);
        }).catch(err =>{
            reject(err.data)        
    })    
});}


/** 
 * post方法,对应post请求 
 * @param {String} url [请求的url地址] 
 * @param {Object} params [请求时携带的参数] 
 */
export function post(url, params) {
    return new Promise((resolve, reject) => {
         axios.post(url, QS.stringify(params))
        .then(res => {
            resolve(res.data);
        })
        .catch(err =>{
            reject(err.data)
        })
    });
}


你可能感兴趣的:(ajax,javascript,前端)