Ajax详解

什么是ajax

  • Ajax 全称为“Asynchronous Javascript And XML”级(异步 JavaScript 和 XML),是一种创建交互式网页应用的网页开发技术,用来实现前后端交互
  • 其核心是XMLHTTPRequest对象,由浏览器提供。通过这个对象可以实现在不重新加载页面的情况下与Web服务器交换数据,使得程序能够更快地回应用户的操作,也就是说ajax可以实现网页的局部刷新
  • 由于每次发出ajax请求都要写很多相同的代码,一个页面一般都有好几个请求,那么会有冗余代码,不仅影响前端开发效率,还影响代码可维护性和可读性,所以可以对ajax进行封装
  • 因为js是单线程的编程语言,一般情况下ajax都会用异步的方式,否则会阻塞后续js代码执行,出现卡顿,影响效率
  • 可以使用promise进一步完善对原生ajax的封装,使用resolve来接收服务器返回的数据,然后用.then方法获取返回结果;同时也可以利用 async/await 语法进一步简化代码
  • axios就是一种通过Promise对ajax的封装,是一个基于Promise的Http库,可以在浏览器和Node.js中使用,可以直接调用.then方法获取服务器返回的数据;axios可以自动转换JSON数据,不需要再用JSON.parse()方法,并且支持配置ajax的请求与响应拦截器,比如可以往里面添加nprogress进度条组件优化用户体验;请求拦截器:发送请求的时候,携带一些信息,比如说token,就是令牌,在用户向服务端请求数据时进行校验,提高安全性;响应拦截器:接收到数据的时候,进行数据过滤、对状态码判断等对应的操作
  • axios是一个第三方库,需要通过npm安装后使用;而ajax是JavaScript的内置对象,无需安装就可以使用,直接new操作

ajax常见的请求方式

● GET:表示向服务器获取资源
● POST:表示向服务器提交信息,通常用于产生新的数据,比如注册
● PUT:表示希望修改服务器的数据, 通常用于修改某数据
● DELETE:表示希望删除服务器的数据
● OPTIONS:发生在跨域的预检请求中,表示客户端向服务器申请跨域提交

GET和POST请求数据区别
  • 使用Get请求时,参数在URL中显示,直接拼接在请求路径后,用一个?间隔,而使用Post请求方式,则请求参数放在xhr.send()里面,并且Post请求需要请求头
  • 使用Get请求时只能携带查询字符串格式;而使用Post请求方式,原则上不限制格式, 但是需要在请求报文的 content-type 做出配置
  • 使用Get请求发送数据量小(2kb左右),Post请求发送数据量大
  • 使用Get请求是明文发送,因为在传输过程,数据被放在请求的URL中,URL中数据会被记录到日志文件,泄漏信息的风险,相对不安全;使用Post请求是暗文发送,Post的所有操作对用户来说都是不可见的,相对安全

老版的ajax

get请求
const xhr = new XMLHttpRequest();
xhr.open("get","请求url?查询字符串",true)
xhr.send()
//获取服务器响应的数据
xhr.onreadystatechange = function(){
    if(xhr.readyState == 4 && xhr.status == 200){
        //获取服务器响应的数据
        xhr.responseText
    }
}

post请求
const xhr = new XMLHttpRequest();
xhr.open("请求方式","请求URL",true)
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded")
xhr.send(`查询字符串`)
//获取服务器响应的数据
xhr.onreadystatechange = function(){
    if(xhr.readyState == 4 && xhr.status == 200){
        //获取服务器响应的数据
        xhr.responseText
    }
}

ajax状态码有哪些
简单来说其实就是用一个数字表明了当前 ajax 运行到哪一步了。
语法: xhr.readyState

  • 0: 创建 ajax 成功
  • 1: 当前 ajax 配置成功
  • 2: 当前 ajax 发送成功(响应已经回到浏览器了)
  • 3: 表示浏览器当前正在解析本次响应, 但可能还没完成
  • 4: 表示浏览器已经完成解析本次响应, 可以正常使用 responseText 了
  • 0 和 1,比较好打印,2/3/4 这几个我们可以借助一个事件去打印。

readyStatechange 事件
通过事件名其实就可以看出,当 readyState 发生改变时就会执行。

const xhr = new XMLHttpRequest()
console.log(xhr.readyState) // 0

xhr.open('GET', 'http://localhost:8888/test/first', true)
console.log(xhr.readyState) // 1

xhr.onreadystatechange = function () {
    if (xhr.readyState === 2) console.log(xhr.responseText) 
    if (xhr.readyState === 3) console.log(xhr.responseText) 
    if (xhr.readyState === 4) console.log(xhr.responseText) 
}

xhr.send()

H5版ajax

get请求
const xhr = new XMLHttpRequest();
xhr.open("请求方式","请求URL?查询字符串",是否异步)
xhr.send();
xhr.onload = function(){
    xhr.responseText
}

post请求
const xhr = new XMLHttpRequest();
xhr.open("请求方式","请求URL",是否异步)
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded")
xhr.send("查询字符串");
xhr.onload = function(){
    xhr.responseText
}

创建ajax的基本步骤

  • 创建ajax对象
const xhr = new XMLHttpRequest()
  • 配置ajax对象
// xhr.open('请求的方式', '请求的地址', 是否异步)
xhr.open('GET', 'http://localhost:8888/test/first', true)
  • 发送请求
xhr.send()
  • 接收响应
xhr.onload = function () {
    console.log('请求回来了~~~~~~~~')
    console.log(xhr.responseText)
}

封装版ajax

封装请求参数  
    请求方式 => get,post
    请求URL => URL(不能为空)
    请求参数 => 可以为空
    是否异步
封装响应
    响应的数据格式 => JSON,对象
    函数 => 利用回调函数获取服务器的数据
<body>
    <button>发送ajax</button>
    <!-- 引入 -->
    <script src="./utils.js"></script>
    <script>
        const btn = document.querySelector("button")
        btn.onclick = function () {
            Ajax({
                url: "http://localhost:8080/login",
                params: {username:'admin',password:123456},
                success(data) {
                    console.log(data);
                }
            })
        }
    </script>
</body>
function Ajax(options) {
    //如果没有URL地址,那么直接报错
    if (!options.url) {
        throw new Error("请输入请求的URL地址")
    }
    //设置默认值
    const paramsDefault = {
        url: "",//请求地址
        type: "get",//请求类名默认为get请求
        params: "",//请参数默认可以没有
        async: true,//是否异步,默认为异步
        resType: 'object',//默认获取的是对象数据
        success() { },//响应的数据通过回调函数获取
    }
    //配置默认参数
    for (let key in options) {
        paramsDefault[key] = options[key]
    }

    //校验请求类型
    if (!(paramsDefault.type.toUpperCase() == "GET" || paramsDefault.type.toUpperCase() == "POST")) {
        throw new Error("请求类型为get或者post请求")
    }

    //请求参数是字符串
    if (!(typeof paramsDefault.params == 'string' || Object.prototype.toString.call(paramsDefault.params) == '[object Object]')) {
        throw new Error("请求参数是一个字符串")
    }

    let str = "";
    if (Object.prototype.toString.call(paramsDefault.params) == '[object Object]') {
        //将对象转换成查询字符串
        // {username:admin,password:123456} => username=admin&password=123456
        for (let key in paramsDefault.params) {
            str += `${key}=${paramsDefault.params[key]}&`
        }
        str = str.slice(0,-1)
        paramsDefault.params = str;
    }
    
    //判断请求是否异步
    if (typeof paramsDefault.async != 'boolean') {
        throw new Error("请求的数据类型是一个boolean类型")
    }

    //判断期望返回的数据类型
    if (!(paramsDefault.resType.toUpperCase() == 'OBJECT' || paramsDefault.resType.toUpperCase() == 'STRING')) {
        throw new Error('期望返回的数据类型是对象或者字符串')
    }

    //回调函数
    if (Object.prototype.toString.call(paramsDefault.success) != '[object Function]') {
        throw new Error("获取数据的方式->回调函数")
    }

    //配置发送Ajax
    if (paramsDefault.type.toUpperCase() == 'GET') {
        //发送get请求
        const xhr = new XMLHttpRequest();
        xhr.open("get", paramsDefault.url + "?" + paramsDefault.params, paramsDefault.async)
        xhr.send();
        xhr.onload = function () {
            //如果paramsDefault.resType == 'object'
            if (paramsDefault.resType.toUpperCase() == 'OBJECT') {
                paramsDefault.success(JSON.parse(xhr.responseText))
            } else {
                paramsDefault.success(xhr.responseText)
            }
        }
    } else {
        //发送post请求
        const xhr = new XMLHttpRequest();
        xhr.open("post", paramsDefault.url, paramsDefault.async)
        xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded")
        xhr.send(paramsDefault.params);
        xhr.onload = function () {
            //如果paramsDefault.resType == 'object'
            if (paramsDefault.resType.toUpperCase() == 'OBJECT') {
                paramsDefault.success(JSON.parse(xhr.responseText))
            } else {
                paramsDefault.success(xhr.responseText)
            }
        }
    }
}

使用promise封装ajax

<button>发送ajax</button>
    <script src="./utils.js"></script>
    <script>
        const btn = document.querySelector("button")
        btn.onclick = function(){
            axiosAjax({
                url:"http://localhost:8080/login",
                params:{username:"admin",password:123456}
            })
            .then(res=>{
                console.log(res);
            })
        }
    </script>
function Ajax(options) {
    //如果没有URL地址,那么直接报错
    if (!options.url) {
        throw new Error("请输入请求的URL地址")
    }
    //设置默认值
    const paramsDefault = {
        url: "",//请求地址
        type: "get",//请求类名默认为get请求
        params: "",//请参数默认可以没有
        async: true,//是否异步,默认为异步
        resType: 'object',//默认获取的是对象数据
        success() { },//响应的数据通过回调函数获取
    }
    //配置默认参数
    for (let key in options) {
        paramsDefault[key] = options[key]
    }

    //校验请求类型
    if (!(paramsDefault.type.toUpperCase() == "GET" || paramsDefault.type.toUpperCase() == "POST")) {
        throw new Error("请求类型为get或者post请求")
    }

    //请求参数是字符串
    if (!(typeof paramsDefault.params == 'string' || Object.prototype.toString.call(paramsDefault.params) == '[object Object]')) {
        throw new Error("请求参数是一个字符串")
    }

    let str = "";
    if (Object.prototype.toString.call(paramsDefault.params) == '[object Object]') {
        //将对象转换成查询字符串
        // {username:admin,password:123456} => username=admin&password=123456
        for (let key in paramsDefault.params) {
            str += `${key}=${paramsDefault.params[key]}&`
        }
        str = str.slice(0,-1)
        paramsDefault.params = str;
    }
    
    //判断请求是否异步
    if (typeof paramsDefault.async != 'boolean') {
        throw new Error("请求的数据类型是一个boolean类型")
    }

    //判断期望返回的数据类型
    if (!(paramsDefault.resType.toUpperCase() == 'OBJECT' || paramsDefault.resType.toUpperCase() == 'STRING')) {
        throw new Error('期望返回的数据类型是对象或者字符串')
    }

    //回调函数
    if (Object.prototype.toString.call(paramsDefault.success) != '[object Function]') {
        throw new Error("获取数据的方式->回调函数")
    }

    //配置发送Ajax
    if (paramsDefault.type.toUpperCase() == 'GET') {
        //发送get请求
        const xhr = new XMLHttpRequest();
        xhr.open("get", paramsDefault.url + "?" + paramsDefault.params, paramsDefault.async)
        xhr.send();
        xhr.onload = function () {
            //如果paramsDefault.resType == 'object'
            if (paramsDefault.resType.toUpperCase() == 'OBJECT') {
                paramsDefault.success(JSON.parse(xhr.responseText))
            } else {
                paramsDefault.success(xhr.responseText)
            }
        }
    } else {
        //发送post请求
        const xhr = new XMLHttpRequest();
        xhr.open("post", paramsDefault.url, paramsDefault.async)
        xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded")
        xhr.send(paramsDefault.params);
        xhr.onload = function () {
            //如果paramsDefault.resType == 'object'
            if (paramsDefault.resType.toUpperCase() == 'OBJECT') {
                paramsDefault.success(JSON.parse(xhr.responseText))
            } else {
                paramsDefault.success(xhr.responseText)
            }
        }
    }
}

//ajax是一个异步代码 => 可以使用promise进行二次封装
function axiosAjax(options){
    return new Promise((resolve,reject)=>{
        Ajax({
            url:options.url || '',
            type: options.type || 'get',
            params: options.params || '',
            async: options.async || true,
            resType: options.resType || 'object',//默认获取的是对象数据
            success(data) {
                //我们要的就是服务器返回的数据,使用resolve进行获取
                resolve(data)
            },
        })
    })
}

axios的用法

axios 是发送ajax的天花板
特点:可以给前端使用 还可以给服务器使用
axios的数据:返回值是在axios返回的data当中
1.导入axios的链接 => bootcdn官网 搜索axios下载axios.min.js
2.使用 => 直接翻官网 axios官网

不使用异步函数的情况
<body>
    <script src="./axios.min.js"></script>
    <button onclick="fn()">通过axios发送ajax</button>
    <script>
function fn1(){
            axios({
                // method:"get"  默认就是get请求 所以可以不写
                // get请求 那么请求参数为请求的url+"?"+查询字符串
                url:`http://localhost:8080/login?username=admin&password=123456`
            })
            .then(res=>{
                console.log(res.data);
            })
         } 
function fn2(){
            axios({
                //post请求 
                method:"post",
                url:"http://localhost:8080/reg",
                data:{
                    username:"bingMIN",
                    password:123456
                }
            })
            .then(res=>{
                console.log(res.data);
            })
         } 

    </script>
</body>
使用异步函数 方式一
<body>
    <script src="./axios.min.js"></script>
    <button onclick="fn()">通过axios发送ajax</button>
    <script>
        async function fn1(){
            const result = await axios({
                // get请求 那么请求参数为请求的url+"?"+查询字符串
                url:`http://localhost:8080/login?username=admin&password=123456`
            })
            console.log(result.data);
        }

        async function fn2(){
            const result = await axios({
                //post请求
                method:"post",
                url:"http://localhost:8080/reg",
                data:{
                    username:"bingMIN",
                    password:123456
                }
            })
            console.log(result.data);
        } 

    </script>
</body>
使用异步函数 方式二
<body>
    <script src="./axios.min.js"></script>
    <button onclick="fn()">通过axios发送ajax</button>
    <script>
        async function fn1(){
            // get请求
            const result = await axios.get("http://localhost:8080/login?username=admin&password=123456")
            console.log(result.data);
        }

       async function fn2(){
            // post请求
            const result = await axios.post("http://localhost:8080/reg",{username:"admin",password:123456})
            console.log(result.data); 
        }

    </script>
</body>

二次封装axios 配置ajax拦截器(请求与响应拦截器)

 <script src="./axios.min.js"></script>
 <button onclick="fn()">通过axios发送ajax</button>
    <script>
        /*
            1.导入axios
            2.创建axios请求实例
                http://localhost:8080/reg 
                http://localhost:8080/login
                http://localhost:8080/xxx
                可以看到前面部分都是相同的  可以进行二次封装
                baseURL => http://localhost:8080
            3.配置ajax拦截器(请求与响应拦截器) 直接看axios官网 搜索拦截器的使用
            4.ajax
         */
        function fn(){
            const instance = axios.create({
                baseURL:"http://localhost:8080", //基本的请求路径
                timeout:1000 //超时时间
            })

            // 配置请求与响应拦截器
            // 添加请求拦截器
            instance.interceptors.request.use(function (config) {
                // 在发送请求之前做些什么
                console.log("请求拦截器");
                return config;
            }, function (error) {
                // 对请求错误做些什么
                return Promise.reject(error);
            });

            // 添加响应拦截器
            instance.interceptors.response.use(function (response) {
                // 对响应数据做点什么
                console.log("响应拦截器");
                return response;
            }, function (error) {
                // 对响应错误做点什么
                return Promise.reject(error);
            });


            // 发送get请求
            /* instance({
                url:"/login?username=wenyuan&password=123456"
            })
            .then(res=>{
                console.log(res.data);
            }) */

            // 发送post请求
            instance({
                method:"post",
                url:"/reg",
                data:{
                    username:"admin",
                    password:123456
                }
            })
            .then(res=>{
                console.log(res.data);
            })
        }
    </script>

ajax二次封装+nprogress的使用

nprogress的使用
1.导入第三方包nprogress的css和js文件 => bootcdn官网 搜索nprogress下载或直接用在线链接
2.nprogress使用方法 翻nprogress官网
NProgress.start() — 显示进度条
NProgress.set(0.4) —设置百分比
NProgress.inc() — 增加一点点
NProgress.done() — 完成进度条

<script src="./axios.min.js"></script>
    <!-- 进度条的css和js行为 -->
    <link href="https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.js"></script>
    <button onclick="fn()">通过axios发送ajax</button>
    <script>
        
        function fn(){
            const instance = axios.create({
                baseURL: 'http://localhost:8080',
                timeout: 1000,
            });
            // 添加请求拦截器
            instance.interceptors.request.use(function (config) {
                // 在发送请求之前做些什么
                // 在请求的时候,开启进度条
                NProgress.start()
                return config;
            }, function (error) {
                // 对请求错误做些什么
                return Promise.reject(error);
            });

            // 添加响应拦截器
            instance.interceptors.response.use(function (response) {
                // 2xx 范围内的状态码都会触发该函数。
                // 对响应数据做点什么
                //关闭进度条
                NProgress.done() 
                return response;
            }, function (error) {
                // 超出 2xx 范围的状态码都会触发该函数。
                // 对响应错误做点什么
                return Promise.reject(error);
            });

            instance({
                method:"post",
                url:"/reg",
                data:{
                    username:"admin",
                    password:123456
                }
            })
            .then(res=>{
                console.log(res.data);
            })
        }
    </script>

参考文章:Ajax和Ajax的封装
参考文章:JavaScript全解析——Ajax

posted @   饼MIN  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示