Ajax学习笔记(一):原生AJAX、HTTP协议、AJAX案例准备工作、发送AJAX请求、AJAX 请求状态

时间:2024-03-18 13:10:31

目录

一、原生AJAX

1.1AJAX 简介

1.2 XML 简介

1.3 AJAX的特点

二、HTTP协议

三、AJAX案例准备工作

四、发送AJAX请求

1.发送GET请求

2.发送POST请求

3.JSON响应

IE缓存问题:

五、AJAX 请求状态


一、原生AJAX

  • 1.1AJAX 简介

AJAX 全称为 Asynchronous JavaScript And XML,就是异步的 JS 和 XML。

通过 AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。

AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式

比如百度搜索框:

搜索abcd,下面出现的提示框就是用到Ajax,提示框中的信息不是自动生成的,而是向服务器发送请求,数据从服务器返回。

注册页面:

当我们输入一个用户名,不可以时,会提示此用户名太受欢迎,请更换一个,也是运用了Ajax。

  • 1.2 XML 简介

        XML 可扩展标记语言。XML 被设计用来传输和存储数据。XML 和 HTML 类似,不同的是 HTML 中都是预定义标签,而 XML 中没有预定义标签,全都是自定义标签,用来表示一些数据。(现在已经被 JSON 取代了。)

 

  • 1.3 AJAX的特点

1.3.1 AJAX的优点

1) 可以无需刷新页面而与服务器端进行通信。

2) 允许你根据用户事件来更新部分页面内容。

1.3.2 AJAX的缺点

1) 没有浏览历史,不能回退

2) 存在跨域问题(同源)

3) SEO 不友好

二、HTTP协议

       HTTP全称为hypertext transport protocol 协议【超文本传输协议】,协议详细规定了浏览器和万维网服务器之间互相通信的规则。

重点是格式与参数:

1.请求报文

行:     GET/POST  /URL  HTTP  协议版本

头:    Host:值  cookie:值  Content-type:值   User-Agent:值 等等

空行:

体:   如果是GET请求体为空,如果是POST可以不为空

2.响应报文

行: HTTP协议版本  响应状态码 响应状态字符串

头: Content-type:值  Content-length:值  Content-encoding:值 等等

体: HTML语法内容

        <html>

              <head>

              </head>

               <body>

                       <h1>月薪过万</h1>

               </body>

       </html>

三、AJAX案例准备工作

1.安装express

只需要在vscode => 终端 => 当前目录中 => 输入npm init --yes。

2.创建一个js文件

在当前目录下新建js文件(不一定非要在express安装的根目录),然后在终端=>当前目录下=>输入 node 文件名 就可以启动服务

报错:Error: listen EADDRINUSE: address already in use :::8000

如果端口被占用,找到前一个服务关闭,在终端CTRL+C端口释放,然后重新再到需要开启服务的终端输入node 文件名

四、发送AJAX请求

1.发送GET请求

点击按钮div:点击按钮发送AJAX请求给服务器,然后把响应体拿过来放到div中。

这部分看不太懂,只是照着敲了一边,后面再回来补。

<button>点击发送请求</button>
 <div id="result"></div>

<script>
      // 获取button元素
      const btn = document.getElementsByTagName('button')[0]
      const result = document.getElementById('result')
      // 绑定事件
      btn.onclick = function () {
        //1. 创建对象
        const xhr = new XMLHttpRequest()
        //2. 初始化 设置请求方法和 url
        xhr.open('GET', 'http:127.0.0.1:8000/server?a=100&b=200&c=300')
        //3. 发送
        xhr.send()
        //4. 事件绑定 处理服务端返回的结果
        // on    当....时候
        // readystate 是 xhr 对象中的属性 , 表示状态 0 1 2 3 4
        //其中0-未初始化 1-open调用完毕 2-send调用完毕 3-服务端返回了部分结果 4-服
务端返回了所有结果
        //change 改变
        xhr.onreadystatechange = function () {
          // 判断(服务器返回了所有的结果)
          if (xhr.readyState === 4) {
            // 判断响应状态码 200   404   403   401    500
            // 2xx  成功
            if (xhr.status >= 200 && xhr.status < 300) {
              //处理结果  行  头  空行  体
              //响应
              // console.log(xhr.status) //状态码
              // console.log(xhr.statusText) //状态字符串
              // console.log(xhr.getAllResponseHeaders()) //所有响应头
              // console.log(xhr.response) //响应体
              // 设置 result 的文本
              result.innerHTML = xhr.response
            }
          }
        }
      }
    </script>

设置url参数:用?隔开,=赋值,&分隔

例如:http://127.0.0.1:8000/server?a=1&b=2&c=3

Server.js 文件:

//1. 引入express
const express = require('express')
//2. 创建应用对象
const app = express()
//3. 创建路由规则
// resquest 是对请求报文的封装
// response 是对响应报文的封装
app.get('/server', (request, response) => {
  // 设置响应头  设置允许跨域
  response.setHeader('Access-Control-Allow-Origin', '*')
  // 设置响应体
  response.send('HELLO AJAX')
})
//4. 监听端口启动服务
app.listen(8000, () => {
  console.log('服务已经启动,8000 端口监听中...')
})

2.发送POST请求

鼠标经过div发送AJAX请求,然后拿回来响应体放在div中

 <div id="result"></div>

传参在send中写,任何类型都可以

可以在xhr.setRequestHeader 设置请求头,不懂可以看下注释

<script>
      // 获取元素对象
      const result = document.getElementById('result')
      // 绑定事件
      result.addEventListener('mouseover', function () {
        //1. 创建对象
        const xhr = new XMLHttpRequest()
        //2. 初始化 设置类型与 URL
        xhr.open('POST', 'http://127.0.0.1:8000/server')
        // 设置请求头:固定写法,第一个参数设置请求体内容类型,第二个参数是参数查询字符串的类型
        xhr.setRequestHeader(
          'Content-Type',
          'application/x-www-form-urlencoded'
        )
        //3. 发送  在这里传值 任何类型都可
        xhr.send('a=100&b=200&c=300')
        // xhr.send('a:100&b:200&c:300')
        // xhr.send('123456')
        //4. 事件绑定
        xhr.onreadystatechange = function () {
          // 判断
          if (xhr.readyState === 4) {
            if (xhr.status >= 200 && xhr.status < 300) {
              // 处理服务端返回的结果
              result.innerHTML = xhr.response
            }
          }
        }
      })
    </script>

server.js

//1. 引入express
const express = require('express')
//2. 创建应用对象
const app = express()
//3. 创建路由规则
// resquest 是对请求报文的封装
// response 是对响应报文的封装
app.post('/server', (request, response) => {
  // 设置响应头  设置允许跨域
  response.setHeader('Access-Control-Allow-Origin', '*')
  // 设置响应体
  response.send('HELLO AJAX POST')
})
//4. 监听端口启动服务
app.listen(8000, () => {
  console.log('服务已经启动,8000 端口监听中...')
})

3.JSON响应

键盘按下任意按下一个按键,就会向服务端发送请求,服务端返回结果,结果在div中呈现

服务端响应体也可以设置为一个数据发送过去,但是不能直接写,要通过JSON.stringify(数据)把数据转换为JSON字符串

app.get('/json-server', (request, response) => {
    //设置响应头
    response.setHeader('Access-Control-Allow-Origin', '*');
    //响应一个数据
    const data = { name: 'atguigu'};
    let str = JSON.stringify(data); //对对象进行字符串转换
    //设置响应体
    response.send(str);
})

(1)手动把JSON字符串转换为js对象

借助JSON.parse(xhr.response)

let data = JSON.parse(xhr.response);
console.log(data);  //js对象:{ name: 'ht' }
result.innerHTML = data.name;

(2)自动把JSON字符串转换为js对象

  借助 xhr.responseType = 'json';

xhr.responseType = 'json';
......
console.log(xhr.response); //js对象:{ name: 'ht' }
result.innerHTML = xhr.response.name;

nodemon实现保存自动重启服务

终端运行npm install -g nodemon安装nodemon,这样每次保存就会自动重启服务,比较方便(副作用是所有html都无法保存时自动调整格式),使用时还是在当前目录nodemon+文件名 ,如

nodemon server.js(之前是node server.js

IE缓存问题:

在一些浏览器中(IE),由于缓存机制的存在,ajax 只会发送的第一次请求,剩

余多次请求不会在发送给浏览器而是直接加载缓存中的数据。

解决方式:浏览器的缓存是根据 url 地址来记录的,所以我们只需要修改 url 地址

即可避免缓存问题

xhr.open("get","/testAJAX?t="+Date.now());

app.get('/ie', (request, response) => {
  // 设置响应头  设置允许跨域
  response.setHeader('Access-Control-Allow-Origin', '*')
  // 设置响应体
  response.send('HELLO IE - 3')
})


 xhr.open('GET', 'http://127.0.0.1:8000/ie?t=' + Date.now()) //获取当前时间戳

2.AJAX请求超时与网络异常处理

服务器写个定时器,3秒后发送响应体

//延时响应
app.get('/delay', (request, response) => {
  // 设置响应头  设置允许跨域
  response.setHeader('Access-Control-Allow-Origin', '*')
  setTimeout(() => {
    // 设置响应体
    response.send('延时响应')
  }, 3000)
})

然后点击按钮发送请求时,可以设置超时xhr.timeout和超时回调xhr.ontimeout,还有网络异常回

xhr.onerror

const xhr = new XMLHttpRequest()
        //超时设置 2s 设置
        xhr.timeout = 2000
        //超时回调
        xhr.ontimeout = function () {
          alert('网络异常,请稍后重试!!!')
        }
        //网络异常回调
        xhr.onerror = function () {
          alert('您的网络似乎出现了一些问题')
        }

浏览器可以手动断网offine

3.AJAX手动取消请求

定时器发送响应体

app.get('/cancel', (request, response) => {
  //设置响应头
  response.setHeader('Access-Control-Allow-Origin', '*')
  //设置响应体
  setTimeout(() => {
    response.send('HELLO 我请求被取消了,没法发过去了')
  }, 3000)
})

写两个按钮

<button>点击发送</button>
    <button>点击取消</button>

取消请求,用xhr.abort()方法,abort中文意思是中止

这里边儿有个作用域的问题,解决方法是把xhr定义在外边给个null,然后赋值xhr实例,再调用方法。(重复赋值不要用const,能用const就用const,不能const就let,反正不能用var)

// 获取元素对象
      const btns = document.querySelectorAll('button')
      let xhr = null
      btns[0].onclick = function () {
        xhr = new XMLHttpRequest()
        xhr.open('GET', 'http://127.0.0.1:8000/cancel')
        xhr.send() // 不用拿响应体,所有后面不写了
      }
      //取消请求 abort
      btns[1].onclick = function () {
        xhr.abort() //先点send再点cancel不会报错,反之报错
        // console.log(xhr)
      }

4.AJAX请求重复发送问题

服务端还是用的前面的定时器,这里重复请求写个逻辑,如果没处在请求中,就创建新的请求;如果已经请求了,就废掉,再重新创建请求。

 // 获取元素对象
      const btns = document.querySelectorAll('button')
      let xhr = null
      // 标识变量
      let isSending = false // 是否正在发送AJAX请求
      btns[0].onclick = function () {
        // 判断标识符变量
        if (isSending) xhr.abort() // 如果正在发生,则取消该请求,创建一个新的请求
        xhr = new XMLHttpRequest()
        // 修改 标识变量的值
        isSending = true
        xhr.open('GET', 'http://127.0.0.1:8000/cancel')
        xhr.send()
        xhr.onreadystatechange = function () {
          if (xhr.readyState === 4) {
            // 修改标识变量 有可能请求失败,所以这里不用再做判断,只要拿到结果,就算请求完成
            isSending = false // 拿到服务器的全部结果后,置为false
          }
        }
      }

五、AJAX 请求状态

xhr.readyState 可以用来查看请求当前的状态

XMLHttpRequest.readyState - Web API 接口参考 | MDN

0: 表示 XMLHttpRequest 实例已经生成,但是 open()方法还没有被调用。

1: 表示 send()方法还没有被调用,仍然可以使用 setRequestHeader(),设定 HTTP请求的头信息。

2: 表示 send()方法已经执行,并且头信息和状态码已经收到。

3: 表示正在接收服务器传来的 body 部分的数据。

4: 表示服务器数据已经完全接收,或者本次接收已经失败了