封装Ajax函数

作者: 新苡米 | 来源:发表于2021-04-05 23:55 被阅读0次

    要实现的效果

    image.png

    定义options参数选项

    itheima() 函数是我们自定义的 Ajax 函数,它接收一个配置对象作为参数,配置对象中可以配置如下属性:

    • method 请求的类型
    • url 请求的 URL 地址
    • data 请求携带的数据
    • success 请求成功之后的回调函数

    处理data参数

    需要把 data 对象,转化成查询字符串的格式,从而提交给服务器,因此提前定义 resolveData 函数如下:

    /*** 处理 data 参数
    * @param {data} 需要发送到服务器的数据
    * @returns {string} 返回拼接好的查询字符串 name=zs&age=10
    */
    function resolveData(data) {
      var arr = []
      for (var k in data) {
        var str = k + '=' + data[k]
        arr.push(str)
      }
    
      return arr.join('&')
    }
    

    定义itheima函数

    在 itheima() 函数中,需要创建 xhr 对象,并监听 onreadystatechange 事件:

    function itheima(options) {
      var xhr = new XMLHttpRequest()
    
      // 把外界传递过来的参数对象,转换为 查询字符串
      var qs = resolveData(options.data)
      // 注册监听
      xhr.onreadystatechange = function () {
      // 注册监听
        if (xhr.readyState === 4 && xhr.status === 200) {
          // 把服务器的json字符串转成js对象
          var result = JSON.parse(xhr.responseText)
          options.success(result)
        }
      }
    }
    

    判断请求的类型

    不同的请求类型,对应 xhr 对象的不同操作,因此需要对请求类型进行 if … else … 的判断:

    if (options.method.toUpperCase() === 'GET') {
      // 发起GET请求
      xhr.open(options.method, options.url + '?' + qs)
      xhr.send()
    } else if (options.method.toUpperCase() === 'POST') {
      // 发起POST请求
      xhr.open(options.method, options.url)
      xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
      xhr.send(qs)
    }
    

    XMLHttpRequest Level2的新特性

    旧版XMLHttpRequest的缺点

    • 只支持文本数据的传输,无法用来读取和上传文件
    • 传送和接收数据时,没有进度信息,只能提示有没有完成

    XMLHttpRequest Level2的新功能

    • 可以设置 HTTP 请求的时限
    • 可以使用 FormData 对象管理表单数据
    • 可以上传文件
    • 可以获得数据传输的进度信息

    设置HTTP请求时限

    有时,Ajax 操作很耗时,而且无法预知要花多少时间。如果网速很慢,用户可能要等很久。新版本的 XMLHttpRequest 对象,增加了 timeout 属性,可以设置 HTTP 请求的时限:


    image.png

    上面的语句,将最长等待时间设为 3000 毫秒。过了这个时限,就自动停止HTTP请求。与之配套的还有一个timeout` 事件,用来指定回调函数:


    image.png
    <script>
      var xhr = new XMLHttpRequest()
      // 设置 超时时间
      xhr.timeout = 30
      // 设置超时以后的处理函数
      xhr.ontimeout = function () {
        console.log('请求超时了!')
      }
      xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks')
      xhr.send()
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4 && xhr.status === 200) {
          console.log(xhr.responseText)
        }
      }
    </script>
    

    FormData对象管理表单数据

    Ajax 操作往往用来提交表单数据。为了方便表单处理,HTML5 新增了一个 FormData 对象,可以模拟表单操作:

     // 1. 新建 FormData 对象
     var fd = new FormData()
     // 2. 为 FormData 添加表单项
     fd.append('uname', 'zs')
     fd.append('upwd', '123456')
     // 3. 创建 XHR 对象
     var xhr = new XMLHttpRequest()
     // 4. 指定请求类型与URL地址
     xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
     // 5. 直接提交 FormData 对象,这与提交网页表单的效果,完全一样
     xhr.send(fd)
    

    FormData对象管理表单数据

    FormData对象也可以用来获取网页表单的值,示例代码如下:

    // 获取表单元素
    var form = document.querySelector('#form1')
    // 监听表单元素的 submit 事件
    form.addEventListener('submit', function(e) {
     e.preventDefault()
     // 根据 form 表单创建 FormData 对象,会自动将表单数据填充到 FormData 对象中
     var fd = new FormData(form)
     var xhr = new XMLHttpRequest()
     xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
     xhr.send(fd)
     xhr.onreadystatechange = function() {}
    })
    

    上传文件

    新版 XMLHttpRequest 对象,不仅可以发送文本信息,还可以上传文件。

    实现步骤:

    ① 定义 UI 结构
    ② 验证是否选择了文件
    ③ 向 FormData 中追加文件
    ④ 使用 xhr 发起上传文件的请求
    ⑤ 监听 onreadystatechange 事件

    定义UI结构

     <!-- 1. 文件选择框 -->
     <input type="file" id="file1" />
     <!-- 2. 上传按钮 -->
     <button id="btnUpload">上传文件</button>
     <br />
     <!-- 3. 显示上传到服务器上的图片 -->
     <img src="" alt="" id="img" width="800" />
    

    验证是否选择了文件

    // 1. 获取上传文件的按钮
    var btnUpload = document.querySelector('#btnUpload')
    // 2. 为按钮添加 click 事件监听
    btnUpload.addEventListener('click', function() {
     // 3. 获取到选择的文件列表
     var files = document.querySelector('#file1').files
     if (files.length <= 0) {
     return alert('请选择要上传的文件!')
     }
     // ...后续业务逻辑
    })
    

    向FormData中追加文件

    // 1. 创建 FormData 对象
    var fd = new FormData()
    // 2. 向 FormData 中追加文件
    fd.append('avatar', files[0])
    

    使用 xhr 发起上传文件的请求

    // 1. 创建 xhr 对象
    var xhr = new XMLHttpRequest()
    // 2. 调用 open 函数,指定请求类型与URL地址。其中,请求类型必须为 POST
    xhr.open('POST', 'http://www.liulongbin.top:3006/api/upload/avatar')
    // 3. 发起请求
    xhr.send(fd)
    

    监听onreadystatechange事件

    xhr.onreadystatechange = function() {
     if (xhr.readyState === 4 && xhr.status === 200) {
         var data = JSON.parse(xhr.responseText)
         if (data.status === 200) { // 上传文件成功
         // 将服务器返回的图片地址,设置为 <img> 标签的 src 属性
            document.querySelector('#img').src = 'http://www.liulongbin.top:3006' + data.url
         } else { // 上传文件失败
             console.log(data.message)
         }
     }
    }
    

    显示文件上传进度

    计算文件上传进度

    新版本的 XMLHttpRequest 对象中,可以通过监听 xhr.upload.onprogress 事件,来获取到文件的上传进度。语法格式如下:

    // 创建 XHR 对象
    var xhr = new XMLHttpRequest()
    // 监听 xhr.upload 的 onprogress 事件
    xhr.upload.onprogress = function(e) {
         // e.lengthComputable 是一个布尔值,表示当前上传的资源是否具有可计算的长度
         if (e.lengthComputable) {
             // e.loaded 已传输的字节
             // e.total 需传输的总字节
             var percentComplete = Math.ceil((e.loaded / e.total) * 100)
         }
     }
    

    导入需要的库

    <link rel="stylesheet" href="./lib/bootstrap.css" />
    <script src="./lib/jquery.js"></script>
    

    基于Bootstrap渲染进度条

     <!-- 进度条 -->
     <div class="progress" style="width: 500px; margin: 10px 0;">
         <div class="progress-bar progress-bar-info progress-bar�striped active" id="percent" style="width: 0%">
         0%
         </div>
     </div>
    

    动态设置到进度条上

    xhr.upload.onprogress = function(e) {
         if (e.lengthComputable) {
             // 1. 计算出当前上传进度的百分比
             var percentComplete = Math.ceil((e.loaded / e.total) * 100)
             $('#percent')
             // 2. 设置进度条的宽度
             .attr('style', 'width:' + percentComplete + '%')
             // 3. 显示当前的上传进度百分比
             .html(percentComplete + '%')
         }
    }
    

    监听上传完成的事件

    xhr.upload.onload = function() {
         $('#percent')
         // 移除上传中的类样式
         .removeClass()
         // 添加上传完成的类样式
         .addClass('progress-bar progress-bar-success')
    }
    

    相关文章

      网友评论

        本文标题:封装Ajax函数

        本文链接:https://www.haomeiwen.com/subject/fxhykltx.html