AJAX基础知识

AJAX全称:async javascript and xml 

ajax核心作用:实现数据请求+客户端渲染  局部刷新

GET请求方式 params 传参

POST请求方式 在body里传参,支持多种格式

<!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>Document</title>
</head>

<body>
  <script src="node_modules/md5/dist/md5.min.js"></script>
  <script src="node_modules/qs/dist/qs.js"></script>
  <script>
/* 
 AJAX核心: 基于XMLHttpRequest创建HTTP请求
    + 创建xhr实例
    
    + 打开一个URL地址 [发送请求前的一些配置信息]
        + method 请求方式:GET(get/delete/head/options...) / POST(post/put/patch)
          GET和POST在官方定义中是没有明确的区别的,但是浏览器或者开发的时候,都会有一套约定俗成的规范
          > GET请求传递给服务器的信息,除了请求头传递以外,要求基于URL问号传参传递给服务器
            xhr.open('GET', './1.JSON?lx=1&name=xxx');
          > POST请求要求传递给服务器的信息,是基于请求主体传递
            xhr.send('lx=1&name=xxx');
            --------------------------------------------------------
          (1) GET传递的信息不如POST多,因为URL有长度限制 [IE 2KB],超过这个长度的信息会被自动截掉,这样导致
             传递内容过多,最后服务器收到的信息是不完整的!! POST理论上是没有限制的,但是传递的东西越多,速度
             越慢,可能导致浏览器传输超时的错误,所以实际上我们会自己动手做限制!!
          (2) GET会产生缓存 [浏览器默认产生的,不可控的缓存] :两次及以上,请求相同的API接口,并且传递的参数
              也一样,浏览器可能会把第一次请求的信息直接返回,而不是从服务器获取最新的信息
              xhr.open('GET', './1.JSON?lx=1&name=xxx&_'+Math.random());
              在请求URL的末尾设置随机数,以此来清除GET缓存的副作用
          (3) POST相对于GET来讲更安全一些:GET传递的信息是基于URL末尾拼接,这个随便做一些劫持或者修改,都可
              以直接改了,而POST请求主体信息的劫持,没那么好做!! 但是"互联网面前,人人都在裸奔"!! 所以不管什么
              方式,只要涉及安全的信息,都需要手动加密 [因为默认所有的信息传输都是明文的]
             --------------------------------------------------------
        + url 请求的URL地址 
        + async 是否采用异步 默认是true
        + username
        + userpass
    + 监听请求的过程,在不同的阶段做不同的处理 [包含获取服务器的响应信息]
        + ajax状态 xhr.readyState
          + 0 UNSENT 未发送
          + 1 OPEND 
          + 2 HEADERS_RECEIVED 响应头信息已经返回
          + 3 LOADING 响应主体信息正在处理
          + 4 DONE 响应主体信息已返回
        + HTTP 状态码 xhr.status / xhr.statusText 
          + 200 OK

        + 获取响应主体信息 xhr.response/responseText/responseXML...
        + 获取响应头信息 xhr.getResponseHeader/getAllResponseHeaders
    + 发送请求 [send中传递的信息,就是设置的请求主体信息]
       基于请求主体传递给服务器的数据格式是有要求的 [Postman接口测试工具]
       1. form-data 主要应用于文件的上传或者表达提交
          xhr.setRequestHeader('Content-Type', 'multipart/form-data')
          ------
          let fd = new FormData
          fd.append('lx', 0)
          fd.append('name', 'xxxs')
          xhr.send(fd)

       2. x-www.form-urlencoded格式的字符串
           格式:"lx=1&name=xxx" [常用]
           Qs库: $npm i qs
           qs.stringify/parse:实现对象的urlencoded格式字符串之间的转换
           xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
           ------
           xhr.send(Qs.stringify({ lx: 0, name: 'xxx' }))
        3. raw 字符串格式
            普通字符串 -> text/plain
            JSON -> application/JSON => JSON.stringify/parse
            XML格式字符串 -> text/xml
            ....
        4. binary 进制数据文件 [buffer/二进制...]
            一般也应用于文件上传
            图片 -> image/jpeg
            EXCEl -> application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
            ...
        5. Graphics


*/

/* let xhr = new XMLHttpRequest();
xhr.open('GET', './1.JSON');
// 设置请求头信息&超时时间&携带资源凭证 需要在open之后send之前
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
// xhr.setRequestHeader('name', '小明'); 请求头信息中不允许出现中文

xhr.onreadystatechange = function() {
  if (xhr.readyState == 4 && xhr.status == 200) {
    console.log(xhr.responseText);
  }
}

xhr.send(null) */
let xhr = new XMLHttpRequest();
xhr.open('GET', 'userInfo?id=1'); // =>router Query
// xhr.open('GET', 'userInfo/1'); // =>router Params
// 后端处理: app.get('/userInfo:id')
xhr.onreadystatechange = function() {
  if (xhr.readyState == 4 && xhr.status == 200) {
    console.log(xhr.responseText);
  }
}

xhr.send(null)
  </script>
</body>

</html>

案例:

倒计时抢购

/* 
两个时间:
        目标时间 18:00:00
        当前时间
    目标时间-当前时间=时间差 [毫秒差: 计算时间差中包含多少小时,多少分钟,多少秒]
    每间隔疫苗中都需要重新获取当前时间 [定时器setInterval],重算时间差等

核心的问题:
    当前时间是不可以获取客户端本地的 (因为本地的时间客户自己可以肆意的修改),需要统一获取服务器的时间 
    [响应头->Date]
    + 获取服务器时间会存在时间偏差问题 --> HEAD AJAX状态码为2 

    在页面不刷新的情况下,每间隔1秒,不是再次从服务器获取 (如果这样:服务器会崩溃,用户得到的时间误差也会越大...)
    而是基于第一次获取的结果之上,手动给其累加到1000ms即可
    
*/
let countdownMoudle = (function () {
    let textBox = document.querySelector('.text'),
        serverTime = 0,
        targetTime = +new Date('2022/7/22 00:00:00'),
        timer = null


    // 获取服务器时间
    const queryServerTime = function () {
        return new Promise((resolve) => {
            let xhr = new XMLHttpRequest
            xhr.open('HEAD', '/')
            xhr.onreadystatechange = () => {
                if ((xhr.status >= 200 && xhr.status < 300) && xhr.readyState === 2) {
                    let time = xhr.getResponseHeader('Date')
                    // 获取的时间是格林宁时间 -> 变为北京时间
                    // console.log(new Date(time);
                    resolve(+new Date(time));
                }
            }
            xhr.send(null)
        })
    }

    // 倒计时计算
    const supplyZero = function supplyZero(val) {
        val = +val || 0
        return val < 10 ? `${val}` : val
    }
    const computed = function computed() {
        let diff = targetTime - serverTime,
            hours = 0,
            minutes = 0,
            seconds = 0
        if (diff <= 0) {
            // 到达抢购时间了
            textBox.innerHTML = '00:00:00';
            clearInterval(timer)

            return
        }
        // 没到时间则计算即可
        hours = Math.floor(diff / (1000 * 60 * 60))
        diff = diff - hours * 1000 * 60 * 60

        minutes = Math.floor(diff / (1000 * 60))
        diff = diff - minutes * 1000

        seconds = Math.floor(diff / 1000)
        textBox.innerHTML = `${supplyZero(hours)}:${supplyZero(minutes)}:${supplyZero(seconds)}`
    }
    return {
        async init() {
            serverTime = await queryServerTime()
            computed()
            // 设置定时器
            timer = setInterval(() => {
                serverTime += 1000
                computed()
            }, 1000)
        }
    }
}

)();
countdownMoudle.init()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值