原生AJAX

发布于:2023-01-17 ⋅ 阅读:(301) ⋅ 点赞:(0)

原生Ajax

1 AJAX 简介

AJAX 全称为 Asynchronous JavaScript And XML,就是异步的 JS 和 XML。
通过 AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。
AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。

比如:注册页面,填用户名,下面可能就会提示用户名重复需要更换,这个时候就是Ajax向服务器发送了请求。
比如:淘宝页面,鼠标移到哪个小图标,就会显示相应的信息,这个就是一种懒加载,按需求加载,Ajax向服务器发请求,返回结果

同步:一定要等任务执行完了,得到结果,才执行下一个任务。
异步:不等任务执行完,直接执行下一个任务。

2 XML 简介

XML 可扩展标记语言。
XML 被设计用来传输和存储数据。

eg:一个数据,前端需要,可以通过网络以XML形式把结果给服务端,服务端就可以使用

XML 和 HTML 类似,不同的是 HTML 中都是预定义标签(a,p等标签),而 XML 中没有预定义标签,全都是自定义标签,用来表示一些数据

HTML是在网页端呈现数据的

服务器端给客户端浏览器返回的结果就是XML格式字符串,前端js接收到结果,对内容进行一个解析,把数据提取出来,对数据做一个处理

eg: 比如说我有一个学生数据

name = "孙悟空" ; age = 18 ; gender = "男" ;
用 XML 表示:
<student>
<name>孙悟空</name>
<age>18</age>
<gender></gender>
</student>

现在已经被 JSON 取代了

JSON 表示:
{"name":"孙悟空","age":18,"gender":"男"}

JSON相对于XML更简洁,数据转换更加容易
之后使用都是用JSON,不用XML

3 AJAX 的特点

3.1 AJAX 的优点

  1. 可以无需刷新页面而与服务器端进行通信。
  2. 允许你根据用户事件(鼠标事件,键盘事件,文档事件等)来更新部分页面内容。

3.2 AJAX 的缺点

  1. 没有浏览历史,不能回退
  2. 存在跨域问题(同源)

跨域:在一个服务向另外一个服务发送请求 eg a.com—>b.com发请求,默认是不可以,但是可以解决

  1. SEO 不友好

SEO Search Engine Optimization 搜索引擎优化 网页内容,爬虫爬不到

4 HTTP 协议

HTTP(Hyper Text Transfer Protocol,HTTP)协议【超文本传输协议】,协议详细的规定了浏览器和万维网服务器之间相互通信的规则

浏览网页绝大多数的数据交换都是用的HTTP协议

协议就是约定,规则,两块内容:请求,响应

在这里插入图片描述

请求报文

向服务器发送请求,四个部分,请求行、头、空行、体
重点是格式于参数

行      GET  /s?ie=utf-8  HTTP/1.1  
头      Host: atguigu.com
        Cookie: name=guigu
        Contenty-type: application/x-www-form-urlencoded
        User-Agent: chrome 83
空行    
体      username=admin&password=admin

行 包括三个部分:
1 GET 请求类型 GET POST
2 /s?ie=utf-8 url路径 对应查询字符串,eg: 搜索谷粒学院/com后面会显示很多参数,就放在这个地方
3 HTTP/1.1 HTTP版本1.1

空行是固定的,必须有

体:可以有内容,也可以没有内容。 如果是GET请求,请求体是空的,如果是POST 请求体可以不为空

响应报文

行    HTTP/1.1  200  OK
头    Content-Type: text/html;charset=utf-8
      Content-length: 2048
      Content-encoding: gzip
空行
体    <html>
        <head>
        </head>
          <body>
            <h1>尚硅谷</h1>
          </body>
      </html>

行 HTTP/1.1(协议版本) 200(响应状态码,eg 404,403,401) OK(响应状态字符串)
体 主要返回的结果 html内容放在响应体

Chrome网络控制台查看通信报文

在这里插入图片描述

在这里插入图片描述

eg 登录网站 processon.com/login
在这里插入图片描述

点击登录,控制台就会发送请求
在这里插入图片描述

在这里插入图片描述

5 node.js的安装

node.js:一个应用程序,可以解析js代码,然后通过js代码对计算机资源进行一个操作

整个ajax应用,需要一个服务端,所以我们安装node.js

网站下载,直接傻瓜式安装即可
检测是否成功安装:
win+R—>cmd—>输入命令:node -v —>出现类似v16.14.0 说明安装成功

6 express框架介绍和基本使用

6.1 express简介

Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具。
使用 Express 可以快速地搭建一个完整功能的网站。

Express 框架核心特性:

  • 可以设置中间件来响应 HTTP 请求。
  • 定义了路由表用于执行不同的 HTTP 请求动作。
  • 可以通过向模板传递参数来动态渲染 HTML 页面。

因为ajax需要给服务端发送请求,需要一个服务端,所以我们选express框架

6.2 安装express框架

首先打开终端(在文件最外层打开)—> 输入 npm init --yes回车 做一个初始化—>安装 输入 npm i express
安装之后会出现三个文件
在这里插入图片描述

6.3 express基本使用

express基本使用.js

// 1 引入express
const { request } = require('express');
const express = require('express');

// 2 创建应用对象
const app = express();

// 3 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
app.get('/', (request, response)=>{
  // 设置响应
  response.send('HELLO EXPRESS');
});

// 4 监听端口启动服务
app.listen(8000, ()=>{
  console.log("服务已经启动, 8000端口监听中...");
})

启动服务
(1) 用node 命令去执行这个脚本
右键express基本使用.js上一层文件(express框架)—> 终端打开 —> 输入命令 node express基本使用.js
在这里插入图片描述

端口监听中

(2) 打开浏览器 输入网址: 127.0.0.1:8000
在这里插入图片描述

发送
在这里插入图片描述

响应
在这里插入图片描述

7 AJAX请求发送前的准备

1 前端页面的准备 2 服务端代码的准备

7.1 前端页面

需求:点击按钮向服务端发送请求,把服务端返回的响应体结果在div做出呈现
1-GET.html

<!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>AJAX GET 请求</title>
  <style>
    #result {
      width: 200px;
      height: 100px;
      border: solid 1px #90b;
    }
  </style>
</head>
<body>
  <!-- 需求:点击按钮向服务端发送请求,把服务端返回的响应体结果在div做出呈现 -->
  <button>点击发送请求</button>
  <div id="result"></div>
</body>
</html>

7.2 服务端代码

把刚刚写的express基本使用.js代码 复制粘贴过来,然后稍作修改
/ —> /server 效果:
客户端浏览器向服务器发送请求时,如果url路径是请求行第二段内容 路径是/server,这时就会执行回调函数((request, response)=>{})里面的代码,并且由response做出响应

// 1 引入express
const express = require('express');

// 2 创建应用对象
const app = express();

// 3 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
app.get('/server', (request, response)=>{
  // 设置响应头  设置允许跨域  
  // 头的名字(Access-Control-Allow-Origin) 头的值(*)
  response.setHeader('Access-Control-Allow-Origin','*')
  // 设置响应体
  response.send('HELLO AJAX');
  
});

// 4 监听端口启动服务
app.listen(8000, ()=>{
  console.log("服务已经启动, 8000端口监听中...");
})

启动服务
右键上一级文件打开终端 —> node server.js
此时会报错,需要关闭之前的端口
在这里插入图片描述

解决方法:ctrl+c释放之前的端口。(其他解决方法:直接关闭软件重新打开就行,再去终端输入命令)

端口号启动成功
在这里插入图片描述

去测试一下 打开浏览器 输入 127.0.0.1:8000/server
在这里插入图片描述

8 AJAX请求的基本操作

还是以上面的案例为支撑
需求:点击按钮向服务端发送请求,把服务端返回的响应体结果在div做出呈现

8.1 核心对象

XMLHttpRequest,AJAX 的所有操作都是通过该对象进行的。

8.2 使用步骤

  1. 创建 XMLHttpRequest 对象
    var xhr = new XMLHttpRequest();
  2. 设置请求信息
xhr.open(method, url);
//可以设置请求头,一般不设置
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  1. 发送请求
xhr.send(body) //get 请求不传 body 参数,只有 post 请求使用
  1. 接收响应
//xhr.responseXML 接收 xml 格式的响应数据
//xhr.responseText 接收文本格式的响应数据
xhr.onreadystatechange = function (){
  if(xhr.readyState == 4 && xhr.status == 200){
    var text = xhr.responseText;
    console.log(text);
  }
}

1-GET.HTML

<!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>AJAX GET 请求</title>
  <style>
    #result {
      width: 200px;
      height: 100px;
      border: solid 1px #90b;
    }
  </style>
</head>
<body>
  <!-- 需求:点击按钮向服务端发送请求,把服务端返回的响应体结果在div做出呈现 -->
  <button>点击发送请求</button>
  <div id="result"></div>

  <script>
    // 获取button元素
    const btn = document.getElementsByTagName('button')[0];
    const result = document.getElementById("result");
    // 绑定事件
    btn.onclick = function() {
      // 1 创建对象
      // xhr XMLHttpRequest缩写,看到xhr要想到时Ajax
      const xhr = new XMLHttpRequest();
      // 2 初始化 设置请求方法和url
      xhr.open('GET', 'http://127.0.0.1:8000/server');
      // 3 发送
      xhr.send();
      // 4 事件绑定 处理服务端返回的结果
      // on  when  当...时候
      // readystate 是xhr对象中的属性  表示状态 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) {
            // 处理结果  行  头  空行  体
            // 1 响应行
            // console.log(xhr.status); // 状态码
            // console.log(xhr.statusText); // 状态字符串
            // console.log(xhr.getAllResponseHeaders()); // 所有响应头
            // console.log(xhr.response); // 响应体
            // // 拿到响应结果之后需要在div做一个呈现

            // 设置 result 的文本
            // 当发送请求就会返回一个结果,在div 并没有刷新,页面就直接显示了文本
            result.innerHTML = xhr.response;
            
          }
        }
      }


    }
  </script>
</body>
</html>

效果:(当发送请求就会返回一个结果,在div 并没有刷新,页面就直接显示了文本)
在这里插入图片描述

`

9 Ajax设置get请求参数(url参数)

在url后面去缀参数
写法:
用问号分割 + 参数名字和值 再用and符分割,& 如果有多个参数
eg:
xhr.open('GET', 'http://127.0.0.1:8000/server?a=100&b=200&c=300');
效果:
在这里插入图片描述

10 Ajax发送post请求

需求:鼠标放在div盒子上面,然后向服务端发送请问POST请求,结果回来以后,把响应体结果在div中做一个呈现

2-POST.html

<!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>AJAX POST 请求</title>
  <style>
    #result  {
      width: 200px;
      height: 100px;
      border: solid 1px #903;
    }
  </style>
</head>
<body>
  <div id="result"></div>
  <script>
    // 获取元素对象
    const result = document.getElementById("result");
    // 绑定事件
    result.addEventListener("mouseover", function() {
      // 1 创建对象
      const xhr = new XMLHttpRequest();
      // 2 初始化 设置类型与 url
      // 还是给8000端口发请求
      xhr.open('POST', 'http:/127.0.0.1:8000/server');
      // 3 发送
      xhr.send();
      // 4 事件绑定
      xhr.onreadystatechange = function() {
        // 判断
        if(xhr.readyState === 4) {
          if(xhr.status >= 200 && xhr.status < 300) {
            // 处理服务端返回的结果
            result.innerHTML = shr.response;
          }
        }
      }
    })
  </script>
</body>
</html>

上面代码运行后会报错,原因是server.js里面目前只有get请求相关代码,而我们现在需要一个post的,可以添加代码到server.js

app.post('/server', (request, response)=>{
  // 设置响应头  设置允许跨域  
  // 头的名字(Access-Control-Allow-Origin) 头的值(*)
  response.setHeader('Access-Control-Allow-Origin','*')
  // 设置响应体
  response.send('HELLO AJAX POST');
});

js代码在改完之后,一定要重新启动服务。
打开终端,停掉之前的服务,再启动服务

10.1 post请求设置请求体(参数)

eg
xhr.send('a=100&b=200&c=300');

也可以写成别的 写法(见代码部分)
在这里插入图片描述

11 Ajax设置请求头信息

// 设置请求头
// Content-Type预定义   
xhr.setRequestHeader('Content-Type','applicatix-www-form-urlencoded');
// name自定义 自定义浏览器会有安全机制 会报错,需要在面加一个特殊的响应头.这个一般都是后端人员做
xhr.setRequestHeader('name', 'atguigtu');
// all 可以接收任意类型的请求
app.all('/server', (request, response)=>{
  // 设置响应头  设置允许跨域  
  // 头的名字(Access-Control-Allow-Origin) 头的值(*)
  response.setHeader('Access-Control-Allow-Origin','*');
  // 响应头
  response.setHeader('Access-Control-Allow-Headers','*');
  // 设置响应体
  response.send('HELLO AJAX POST');
});

12 服务端响应JSON数据

实际工作,我们向服务端发送请求,服务端返回结果,绝大多数都是一个JSON格式的数据

需求:键盘按下,向服务端发送请求,服务端返回结果呈现在div中
eg. 3-POST.html

<!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>JSON响应</title>
  <style>
    #result {
      width: 200px;
      height: 100px;
      border: solid 1px #89b;
    }
  </style>
</head>
<body>
  <div id="result"></div>
  <script>
    // 绑定键盘按下事件
    window.onkeydown = function() {
      // 发送请求
      const xhr = new XMLHttpRequest();
      // 设置响应体数据的类型
      xhr.responseType = 'json';
      // 初始化
      xhr.open('GET', 'http://127.0.0.1:8000/json-server');
      // 发送
      xhr.send();
      // 事件绑定
      xhr.onreadystatechange = function() {
        if(xhr.readyState === 4) {
          if(xhr.status >= 200 && xhr.status < 300) {
            // console.log(xhr.response);
            // result.innerHTML = xhr.response;
            // 手动对数据转换
            // let data = JSON.parse(xhr.response);
            // console.log(data);
            // result.innerHTML = data.name;
            // 自动转换
            console.log(xhr.response);
            result.innerHTML = xhr.response.name;
            
            
          }
        }
      }
    }
  </script>
</body>
</html>



app.all('/json-server', (request, response)=>{
  // 设置响应头  设置允许跨域  
  // 头的名字(Access-Control-Allow-Origin) 头的值(*)
  response.setHeader('Access-Control-Allow-Origin','*');
  // 响应头
  response.setHeader('Access-Control-Allow-Headers','*');
  // 响应一个数据  对象
  const data = {
    name: 'atguigu'
  }
  // 将对象惊醒字符串转换
  let str = JSON.stringify(data)
  // 设置响应体
  // 这个send里面只能接收字符串和...
  response.send(str);

});

13 nodemon自动重启工具安装

nodemon:帮助我们自动重启服务、应用

由于之前更改server.js每次我们都会重启服务,很麻烦,所以我们就使用这个工具

安装:(前提是安装好nodejs)
1 首先关闭服务
2 打开命令行,输入 npm install -g nodemon 等待下载好
3 重新启动服务 输入nodemon server.js (与之前指令不同)
在这里插入图片描述

4 现在,当直接修改server.js里面代码再保存,终端就会接着自动启动服务,显示8000端口监听中
在这里插入图片描述

14 解决 IE 缓存问题

问题:在一些浏览器中(IE),由于缓存机制的存在,ajax 只会发送的第一次请求,剩余多次请求不会在发送给浏览器而是直接加载缓存中的数据。

IE浏览器会对Ajax的请求结果去做一个缓存,把结果缓存起来,这样就会导致下一次发送请求时走的是本地缓存,而不是服务器返回的最新数据,这样对于时效性强的擦汗场景,Ajax缓存会影响结果,不能正常显示,所以我们需要去解决这个问题。

解决方式:浏览器的缓存是根据 url 地址来记录的,所以我们只需要修改 url 地址
即可避免缓存问题
xhr.open("get","/testAJAX?t="+Date.now());

这些问题工具都会给我们加好,我们只需要知道这个IE缓存问题

eg. 4-IE缓存问题.html


<!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>IE缓存问题</title>
  <style>
    #result {
      width: 200px;
      height: 100px;
      border: solid 1px #258;
    }
  </style>
</head>
<body>
  <button>点击发送请求</button>
  <div id="result"></div>
  <script>
    const btn = document.getElementsByTagName('button')[0];
    const result = document.querySelector("#result");

    btn.addEventListener('click', function() {
      // 向服务端发送请求
      const xhr = new XMLHttpRequest();
      xhr.open('GET','http://127.0.0.1:8000/ie?t='+Date.now());
      xhr.send();
      xhr.onreadystatechange = function() {
        if(xhr.readyState === 4) {
          if(xhr.status >= 200 && xhr.status < 300) {
            result.innerHTML = xhr.response;
            
          }
        }
      }
    })
  </script>
</body>
</html>

// 针对 IE 缓存
app.get('/ie', (request, response)=>{
  // 设置响应头  设置允许跨域  
  // 头的名字(Access-Control-Allow-Origin) 头的值(*)
  response.setHeader('Access-Control-Allow-Origin','*')
  // 设置响应体
  response.send('HELLO IE -2');
  
});

15 Ajax请求超时和网络异常处理
需求:点击按钮发送请求给服务端,服务端返回结果在div中呈现。
如果2s后没有返回结果,就提示网络超时
eg 5-超时与网络异常.html

<!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>
  <style>
    #result {
      width: 200px;
      height: 100px;
      border: solid 1px #90b;
    }
  </style>
</head>
<body>
  <button>点击发送请求</button>
  <div id="result"></div>
  <script>
    const btn = document.getElementsByTagName('button')[0];
    const result = document.querySelector("#result");

    btn.addEventListener('click', function() {
      // 向服务端发送请求
      const xhr = new XMLHttpRequest();
      // 超时设置 2s 设置   (2s内没有结果,请求就取消)
      xhr.timeout = 2000;
      // 超时回调
      xhr.ontimeout = function() {
        alert("网络异常,请稍后重试!!");
      }
      // 网络异常回调
      xhr.onerror = function() {
        alert("你的网络似乎有问题!!")
      }


      xhr.open('GET','http://127.0.0.1:8000/delay');
      xhr.send();
      xhr.onreadystatechange = function() {
        if(xhr.readyState === 4) {
          if(xhr.status >= 200 && xhr.status < 300) {
            result.innerHTML = xhr.response;
            
          }
        }
      }
    })
  </script>
</body>
</html>

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

其中:无网络可以这样设置
在这里插入图片描述

15 Ajax取消请求

在结果还没有返回之前,通过代码手动取消请求

eg. 6-取消请求.html

<!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>
</head>
<body>
  <button>点击发送</button>
  <button>点击取消</button>
  <script>
    const btns = document.querySelectorAll('button');
    let x = null;
    // x 不能用 const 使用会报错

    btns[0].onclick = function() {
      x = new XMLHttpRequest();
      x.open("GET",'http://127.0.0.1:8000/delay');
      x.send();
    }

    // abort
    btns[1].onclick = function() {
      x.abort();

    }
  </script>
</body>
</html>

在这里插入图片描述

15 Ajax请求重复发送问题

当服务器响应很慢时,用户一直点击发送请求,这时服务器压力会很大,会接收到很多相同请求。我们要解决这个问题,当用户发送相同请求时,我们就去取消这个请求

eg. 7-重复请求问题.html

<!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>
</head>
<body>
  <button>点击发送</button>
  
  <script>
    const btns = document.querySelectorAll('button');
    let x = null;
    // 标识变量
    let isSending = false; // 是否正在发送AJAX请求


    btns[0].onclick = function() {
      // 判断元素对象
      if(isSending) x.abort(); // 如果正在发送,则取消该请求,创建一个新请求
      x = new XMLHttpRequest();  // 对象创建出来了,此时肯定在发送Ajax请求 true
      // 修改 标识变量的值
      isSending = true;
      x.open("GET",'http://127.0.0.1:8000/delay');
      x.send();
      // 当整个状态为4 时 请求完成  
      // 不需要加状态码判断,很可能请求是一个失败请求,如果在成功里面做判断,这个变量永远不能为false
      x.onreadystatechange = function() {
        if(x.readyState === 4) {
          // 修应该标识变量
          isSending = false;
        }
      }
    }


  </script>
</body>
</html>

在这里插入图片描述

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到