Ajax工作原理(节流. 防抖)

232 阅读5分钟

1.1-HTTP协议原理与ajax工作原理


  1. http协议 : 网络传输协议
  • 协议 : 规定网络数据传输格式
  1. http协议组成 : 请求报文 + 响应报文
  • 浏览器发请求 必须是 : 请求报文

  • 服务器响应 必须是 : 响应报文

  1. 请求报文 由三部分组成

3.1 请求行 : 请求方法 + 请求地址

3.2 请求头 : 浏览器告诉服务器,我发送给你的数据是什么格式 (文本、json、图片、音视频等等)

3.3 请求体 : 请求参数

  1. 响应报文 由三部分组成

4.1 响应行 : 服务器状态码、 服务器地址等

2xx : 请求成功 200:成功

3xx : 重定向 302 服务端重定向(服务器主动修改浏览器网址)

4xx : 前端的问题 404 : url错误 400: 参数错误 403/402 : 没有权限 405:请求方法错误

5xx : 服务器的问题 500 服务器挂了(后台java代码像js一样爆红了)

4.2 响应头 : 服务器告诉浏览器,我响应给你的数据是什么格式 (文本、json、图片、音视频等等)

4.3 响应体 : 服务器响应数据

5.ajax原理 : 发送请求报文过程

  • 给服务器发请求,其实发的就是请求报文

网页从输入url到呈现过程

  1. DNS解析: 把域名解析成IP地址
  2. TCP链接三次握手: 建立 安全可靠的传输协议

2.1什么是TCP 一种传输控制协议

2.2TCP作用: 保证http网络传输是安全可靠的 (检测客户端 与服务器的网卡是不是通的)

2.3 TCP三次握手:

第一次: 浏览器=>服务器 (你能听到我说话吗,检测浏览器:发送)

第二次:服务器=>浏览器(我听到了,你能听到我说话吗, 检测服务器: 接收 +发送)

第三次:浏览器=>服务器(嗯,我听到了,检测浏览器:接收)

三次握手完成,TCP客户端与服务器成功建立链接,开始进行http网络传输

大概分为4个流程

  1. HTTP请求: 网络传输协议

3.1 浏览器发送请求

3.2服务器发处理请求

3.3服务器响应请求

4.服务器响应数据之后,渲染引擎开始渲染页面

4.1解析html生成 dom树

4.2解析css生成,样式树

4.3dom树 与 样式树 合并得到 渲染树

4.4呈现页面

5.断开链接

2.1 什么是TCP: 一种传输控制协议

2.2 TCP作用:保证HTTP网络传输是 安全+可靠的(检测客户端)

02-文件上传

1.1-文件上传思路


 /*文件上传 
      1.前置知识点
        1.1 file表单, 默认自带点击事件,作用是选择文件
        1.2 上传文件‘必须’要使用原生内置的FormData对象
          (1)文件需要设置单独的请求头 : multipart/form-data
          (2)文件以二进制方式传输(文本是utf8编码,但是文件不是)
        1.3 file表单有一个特殊的事件onchange事件 : 用户选择了文件就会执行

      2.文件上传流程
        2.1 在file表单的onchange事件中获取用户选择的图片
           this.files[0]
        2.2 创建FormData对象,将图片添加到fd对象中
          let fd = new FormData()
          fd.append('接口参数',文件数据)
        2.3 ajax发送请求 : 参数必须是formdata对象
       */
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>案例-头像上传</title>
    <link rel="stylesheet" href="./lib/bootstrap-v4.6.0.css" />
    <style>
      .thumb-box {
        text-align: center;
        margin-top: 50px;
      }

      .thumb {
        width: 250px;
        height: 250px;
        object-fit: cover;
        border-radius: 50%;
      }
    </style>
  </head>

  <body>
    <div class="thumb-box">
      <!-- 头像 -->
      <img src="./images/cover.jpg" class="img-thumbnail thumb" alt="" />
      <div class="mt-2">
        <!-- 文件选择框 -->
        <!-- accept 属性表示可选择的文件类型 -->
        <!-- image/* 表示只允许选择图片类型的文件 -->
        <input type="file" id="iptFile" accept="image/*" />
        <br />
      </div>
    </div>

    >
    <script src="./lib/axios.js"></script>

    <script>
      
      //1.给file表单注册onchange事件 
      document.querySelector('#iptFile').onchange = function(){
        // console.log( this )//file表单
        //2.获取用户选择的文件
        /* 
        this.files : 伪数组,存储所有的选中的文件
        this.files[0] : 取出第一个文件
         */
        console.log( this.files[0] )
        //3.创建FormData对象
        let fd =  new FormData()
        //4. 调用append方法追加文件
        fd.append('avatar', this.files[0] )
        //5. ajax发送请求
        axios({
          url:'http://www.liulongbin.top:3009/api/upload/avatar',
          method:'post',
          /* 将formdata对象作为参数, fd对象会自动帮我们设置请求头,自动处理文件参数 */
          data:  fd,
        }).then(res=>{
          //成功回调
          console.log(res)
          //6.显示上传成功的图片
          document.querySelector('img').src = `http://www.liulongbin.top:3009${res.data.url}`
        })
      }
  
    </script>
    
  </body>
</html>

1.2-自定义文件上传按钮


file表单自带的按钮样式太丑,我们可以自定义一个文件上传按钮

文件预览固定代码(工作中CV)

/*

1.文件预览功能

2.点击新增: Ajax提交数据(名字 技能 图形)

*/



    //文件预览 由 四个固定步骤组成
    //1.给file表单注册onchange事件:   用于选择文件
    document.querySelector('#heroIcon').onchange = function () {
      //2.获取用户选择的文件
      let file = this.files[0]
      console.log(file)
      //3.将file对象转化为url路径
      let url = URL.createObjectURL(file)
      console.log(url)
      //4.将url路径设置给img标签的src
      document.querySelector('.preview').src = url
    }

案例

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>案例-头像上传</title>
    <link rel="stylesheet" href="./lib/bootstrap-v4.6.0.css" />
    <style>
      .thumb-box {
        text-align: center;
        margin-top: 50px;
      }

      .thumb {
        width: 250px;
        height: 250px;
        object-fit: cover;
        border-radius: 50%;
      }
    </style>
  </head>

  <body>
        <a href="http:www.baidu.com">111</a>
    <div class="thumb-box">
      <!-- 头像 -->
      <img src="./images/cover.jpg" class="img-thumbnail thumb" alt="" />
      <div class="mt-2">
        <!-- 文件选择框 -->
        <!-- accept 属性表示可选择的文件类型 -->
        <!-- image/* 表示只允许选择图片类型的文件 -->
        <input
          type="file"
          id="iptFile"
          accept="image/*"
          style="display: none"
        />
        <br />
        <!-- 选择头像图片的按钮 -->
        <button class="btn btn-primary" id="btnChoose">
          选择 & 上传图片
        </button>
      </div>
    </div>

    

    <script src="./lib/axios.js"></script>
    <script>
      /*自定义文件上传按钮思路
      (1)隐藏file表单
      (2)给自定义按钮添加一个点击事件
      (3)点击按钮的时候,触发 file表单的点击 
       */

    document.querySelector('#btnChoose').onclick = function(){
        /* 
        dom对象.onclick()  :  只能触发你自己注册的onclick事件,没注册触发不了
        dom对象.click() : 模拟鼠标点击。 触发注册的onclick事件 + 默认点击事件
        */
        document.querySelector('#iptFile').click()
    }


      //1. file类型表单自带一个选择文件点击按钮,当用户选择文件之后就会触发onchange事件
      document.querySelector("#iptFile").onchange = function() {
        //this : file表单
        //(1)获取用户选择的文件
        let file = this.files[0]
        // 非空判断,如果内容为undefined,给出提示
        if (file == undefined) {
          return alert("请选择上传文件!")
        }
        //(2)创建FormData对象, 只有FormData对象才可以上传文件
        let fd = new FormData()
        //(3)添加文件
        fd.append("avatar", file)
        //(4)发送ajax请求, 参数为 FormData对象
        axios({
          method: "POST",
          url: "http://www.liulongbin.top:3009/api/upload/avatar",
          data: fd
        }).then(({ data: res }) => {
          console.log(res)
          if (res.code != 200) {
            return alert(res.message)
          }
          // 成功后提示,修改图片路径
          alert("恭喜您,上传头像成功!")
          document.querySelector(
            "img"
          ).src = `http://www.liulongbin.top:3009${res.url}`
        })
      }
    </script>
  </body>
</html>

常见控制台错误

  • 200成功
  • 302.重定向
  • 400参数错误
  • 404路径 错误
  • 403无权限,必须登录才能访问
  • 405请求方法错误
  • 413 响应状态 413 Payload Too Large表示主体的大小超过了服务器愿意或有能力处理客户端的关闭请求,服务器可能会(可以)连接以阻止发送该请求。Payload请求体
  • 500服务器错误

1.1-函数防抖


1.函数防抖 : 单位时间内,频繁触发一个事件, 以'最后一次'触发为准

2.防抖应用场景: 输入框输入事件

3.防抖流程 :

3.1 声明一个全局变量存储定时器ID

3.2 每一次触发交互的时候,先清除上一次定时器。 然后把本次事件处理代码放入定时器中

let timeID = null
        //输入框输入事件
        document.querySelector('input').oninput = function(){            
            //1.先清除之前的定时器
            clearTimeout(timeID)
            //2.开启本次定时器
            timeID = setTimeout(()=>{
                //function函数: this->window
                //箭头函数  this->上级this 表单
                console.log(`发送ajax,搜索内容是${this.value}`)
            },500) 
        }

1.2-函数节流


1.函数节流 : 单位时间内,频繁触发一个事件, 只会触发一次

2.节流场景 : 解决高频事件 (滚动条事件高频触发)

3.节流实现:

3.1 声明一个全局变量存储触发时间 let lastTime = null

3.2 每一次触发事件,获取当前时间 let currentTime = Date.now()

3.3 判断 当前时间 与 上一次触发时间,是否超过间隔 currentTime-lastTime>=500

3.4 如果超过触发间隔,则执行事件处理代码。 然后存储本次触发事件 lastTime = currentTime

//声明一个全局变量存储触发时间
        let lastTime = null

        window.onscroll = function(){
            //1.每一次触发,先获取本次时间戳
            let currentTime = Date.now()
            //2.判断当前时间 与 上一次触发时间 是否超过间隔
            if( currentTime - lastTime >= 500 ){
                console.log( document.documentElement.scrollTop)
                //3.存储本次触发时间
                lastTime = currentTime
            }
            
        }