AJAX

简介

什么是 AJAX?

AJAX = Asynchronous JavaScript And XML.

AJAX 并非编程语言。

AJAX 仅仅组合了:

  • 浏览器内建的 XMLHttpRequest 对象(从 web 服务器请求数据)

  • JavaScript 和 HTML DOM(显示或使用数据)

Ajax 是一个令人误导的名称。Ajax 应用程序可能使用 XML 来传输数据,但将数据作为纯文本或 JSON 文本传输也同样常见。

Ajax 允许通过与场景后面的 Web 服务器交换数据来异步更新网页。这意味着可以更新网页的部分,而不需要重新加载整个页面。

AJAX特点

ajax优点

1)可以无需刷新页面而与服务器端进行通信。
2)可以根据用户事件更新部分页面内容

ajax缺点

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

工作原理

  1. 事件触发:如点击按钮或页面加载

  2. AJAX请求:通过 JavaScript 创建一个 XMLHttpRequest 对象,向服务器发送请求。

  3. 服务器处理请求:服务器(通常使用 PHP、Node.js 等)接收请求,处理并返回响应数据(JSON、XML、HTML等)。

  4. AJAX响应处理:浏览器接收响应,使用 JavaScript 在页面上更新内容,而无需重新加载整个页面。

XMLHttpRequest 对象:

  • XMLHttpRequest 对象是 AJAX 的基石。

    1. 创建 XMLHttpRequest 对象

    2. 定义回调函数

    3. 打开 XMLHttpRequest 对象

    4. 向服务器发送请求

  • 所有现代浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject)。

  • XMLHttpRequest 用于在后台与服务器交换数据。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

创建

  • 语法:变量 = new XMLHttpRequest()

方法

  1. new XMLHttpRequest():创建新的 XMLHttpRequest 对象。

  2. abort(): 取消当前请求。

  3. getAllResponseHeaders():返回头部信息。

  4. getResponseHeader():返回特定的头部信息。

  5. open(method, url, async, user, psw):

    1. 规定请求:

      1. method:请求类型 GET 或 POST

      2. url:文件位置

      3. async:true(异步)或 false(同步)

      4. user:可选的用户名

      5. psw:可选的密码

  6. send():发送请求。

对象属性

  1. onreadystatechange:定义当 readyState 属性发生变化时调用的函数。

  2. readyState:保存 XMLHttpRequest 的状态。值为:

    1. 0:请求未初始化

    2. 1:服务器连接已建立

    3. 2:请求已收到

    4. 3:正在处理请求

    5. 4:请求已完成且响应已就绪

  3. responseText:以字符串形式返回响应数据。

  4. responseXML:以 XML 数据返回响应数据。

  5. status:返回请求的状态码。

    • 200: "OK"

    • 403: "Forbidden"

    • 404: "Not Found"

  6. statusText:返回状态文本(比如 "OK" 或 "Not Found")

  • onreadystatechange属性

xhr.onreadystatechange = function(){
   //判断 (服务端返回了所有的结果)
   if(xhr.readyState === 4){
      //判断响应的状态码
      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;
      }
    }

GET 还是 POST?

GET 比 POST 更简单更快,可用于大多数情况下。

不过,请在以下情况始终使用 POST:

  • 缓存文件不是选项(更新服务器上的文件或数据库)

  • 向服务器发送大量数据(POST 无大小限制)

  • 发送用户输入(可包含未知字符),POST 比 GET 更强大更安全

GET


<button>点击发送请求</button>
<div id="result"></div>
    <script>
        //获取button元素
        const button = document.querySelector('button');
        const result = document.querySelector('#result');
        
        //绑定点击事件
        button.addEventListener('click', function(){
            //创建对象
            const xhr = new XMLHttpRequest();
            
            //初始化,设置请求方式和请求地址 方法open()
            xhr.open('GET', 'http://127.0.0.1:4000/server?a=100&b=200&c=300');
            
            //发送
            xhr.send();
            
            //事件绑定 处理服务端返回的结果
            xhr.onreadystatechange = function(){
                //判断 (服务端返回了所有的结果)
                if(xhr.readyState === 4){
                    //判断响应的状态码
                    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;
                   }
                }
            }                               
        })


POST

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ajax Post请求</title>
    <style>
        #result{
            width: 200px;
            height: 100px;
            border:1px solid #903;
        }
    </style>
</head>
<body>
    <div id="result"></div>
    <script>
        //获取元素对象
        const result = document.getElementById('result');
        //绑定事件
        result.addEventListener('mouseenter', function(){
            //1、创建对象
            const xhr = new XMLHttpRequest();
            
            //2、设置请求方式和请求地址
            xhr.open('POST', 'http://127.0.0.1:3000/server');
            
            //设置请求头 Content-Type设置请求体内容的类型 application/x-www-form-urlencoded参数查询字符串的固定类型
            xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
            
            //3、发送
            xhr.send('a:100&b:200&c:300')
            //4、事件绑定
            xhr.onreadystatechange = function(){
                if(xhr.readyState === 4){
                    if(xhr.status >= 200 && xhr.status < 300){
                   //处理服务端返回的结果
                    result.innerHTML = xhr.response
                    }
                }
            }
        })     
    </script>
</body>
</html>

JSON对象

简介

JavaScript 对象表示法 (JSON) 是一种基于文本的标准格式,用于表示基于 JavaScript 对象语法的结构化数据。它通常用于在 Web 应用中传输数据(例如,将一些数据从服务器发送到客户端,以便可以在网页上显示,反之亦然)。

JSON 以字符串形式存在 - 当你想要通过网络传输数据时很有用。当你想要访问数据时,需要将其转换为原生 JavaScript 对象。

  • 反序列化:将字符串 转换为 原生对象

  • 序列化:将原生对象 转换为 字符串 以便可以通过网络传输

JSON 字符串可以存储在自己的文件中,该文件基本上只是一个扩展名为 .json、MIME type 为 application/json 的文本文件。

JSON结构

JSON 是一个字符串,其格式非常类似于 JavaScript 对象文字格式。可以在 JSON 中包含与标准 JavaScript 对象中相同的基本数据类型 - 字符串、数字、数组、布尔值和其他对象文字。这允许构建数据层次结构,如下所示:

{
  "squadName": "Super hero squad",
  "homeTown": "Metro City",
  "formed": 2016,
  "secretBase": "Super tower",
  "active": true,
  "members": [
    {
      "name": "Molecule Man",
      "age": 29,
      "secretIdentity": "Dan Jukes",
      "powers": ["Radiation resistance", "Turning tiny", "Radiation blast"]
    },
    {
      "name": "Madame Uppercut",
      "age": 39,
      "secretIdentity": "Jane Wilson",
      "powers": [
        "Million tonne punch",
        "Damage resistance",
        "Superhuman reflexes"
      ]
    },
    {
      "name": "Eternal Flame",
      "age": 1000000,
      "secretIdentity": "Unknown",
      "powers": [
        "Immortality",
        "Heat Immunity",
        "Inferno",
        "Teleportation",
        "Interdimensional travel"
      ]
    }
  ]
}

要进一步访问层次结构中的数据,必须将所需的属性名称和数组索引链接在一起。例如,要访问成员列表中列出的第二个英雄的第三个超级大国:

superHeroes["members"][1]["powers"][2];
  1. 首先,我们有变量名 - superHeroes。

  2. 在其中,我们想要访问 members 属性,因此我们使用 ["members"]。

  3. members 包含一个由对象填充的数组。我们想要访问数组内的第二个对象,因此我们使用 [1]。

  4. 在这个对象内部,我们想要访问 powers 属性,所以我们使用 ["powers"]。

  5. powers 属性内部是一个包含所选英雄超能力的数组。我们想要第三个,所以我们使用 [2]。

JSON格式

  • 数据采用名称/值对

  • 数据以逗号分隔

  • 对象封装在左括号和右大括号内

  • 空对象可以用{}

  • 数组封装在左方括号和右方括号中

  • 空数组可以用[]

  • 成员由双引号中包含的键值对表示

  • 每个成员在对象结构中都应该有一个唯一的键

  • 如果成员是字符串,则成员的值必须包含在双引号中

  • 布尔值使用小写的 or 文字表示truefalse

  • 数字值使用双精度浮点格式表示,并且不应包含前导零

  • 字符串中的“冒犯性”字符需要使用反斜杠字符进行转义\

  • Null 值由小写的文本表示null

  • 日期和类似的对象类型没有得到充分支持,应该转换为字符串

  • 对象或数组值的每个成员都必须后跟一个逗号,最后一个成员除外

  • JSON 文件的标准扩展名为'.json'

  • JSON 文件的 MIME 类型为'application/json'


//1.定义基本格式
const person = {"name": "张三", age: 23, 'gender': true};
const ps = [{"name": "张三", "age": 23, "gender": true},
          {"name": "李四", "age": 24, "gender": true},

JSON和JS对象互转

JSON字符串转换为JS对象,使用JSON.parse()方法

const obj = JSON.parse('{"a":"Hello","b":"World"}')//结果是:{a:'Hello',b:'World'}

JS 对象转换为JSON字符串,使用JSON.stringify()方法

const json = JSON.stringify('{a:'Hello',b:'World'}')//结果是:{"a":"Hello","b":"World"}

注意

  • JSON 纯粹是一个具有指定数据格式的字符串 - 它只包含属性,不包含方法。

  • JSON 要求在字符串和属性名称周围使用双引号。除了包围整个 JSON 字符串之外,单引号无效。

  • JSON 实际上可以采用任何可有效包含在 JSON 中的数据类型的形式,而不仅仅是数组或对象。例如,单个字符串或数字就是有效的 JSON。

  • 与 JavaScript 代码中对象属性可以不加引号不同,在 JSON 中,只能将带引号的字符串用作属性。

IE 缓存问题

IE浏览器会缓存网页中的GET和XHR的内容,并且在IE浏览器中如果请求方式是get方式的话,IE浏览器会进行识别,如果该get请求的URL是第一次请求的话,会请求项目的后台,从数据库中获取数据,如果该get请求的URL不是第一次请求的话,那么该URL就不会请求项目后台,IE浏览器会直接从缓存中拿到上次该URL获取的数据,无论是什么插件的get方式请求,IE浏览器都会这样进行处理的。

IE浏览器会对相同请求的AJAX,进行缓存,当你删除数据后,在调用同样的接口,IE不会刷新,只会把第一次请求该接口的数据拿出来,所以,你看到的页面永远都是第一次请求的AJAX返回的数据

解决方法

  1. 方法一:提交方式是get方式,但是在传递的参数中添加一个随机数或当前时间戳的参数,从而保证每次URL请求唯一性,从而解决在IE浏览器中从数据库中获取数据:

//向服务器获取新的结果通过获取时间戳,防止IE浏览器走缓存
xhr.open('GET','http://127.0.0.1:3000/ie?t='+Date.now())

2. 方法二:提交方式修改为post方法,这样就不会出现这样的问题了。

超时与网络异常

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>请求超时与网络异常</title>
    <style>
        #result{
            width: 200px;
            height: 100px;
            border:1px solid #90b;
        }
    </style>
</head>
<body>
    <button>点击发送请求</button>
    <div id="result"></div>
    <script>
        const btn = document.querySelector('button')
        const result = document.getElementById('result')

        btn.addEventListener('click',function(){
            const xhr = new XMLHttpRequest()

            //超时设置 2s
            xhr.timeout = 2000
            //超时回调
            xhr.ontimeout = function(){
                alert("网络异常,请稍后重试")
            }
            //网络异常回调
            xhr.ontimeout = function(){
                alert("你的网络似乎出了一些问题")
            }
            xhr.open('GET','http://127.0.0.1:3000/delay')
            xhr.send()
            xhr.onreadystatechange = function(){
                if(xhr.readyState === 4)
                {
                    if(xhr.status >= 200 && xhr.status <300){
                        result.innerHTML = xhr.response
                    }
                }
            }
        })
    </script>
</body>
</html>

重复请求问题

当用户频繁并重复请求相同的功能时,如果不处理,服务器会依次响应用户的每一次请求,这样容易导致响应时间过长,用户体验不好。因此可以在每件事件触发请求时,标识一个变量判断该请求是否正在发送,如果正在发送,就取消该请求,创新一个新的请求,保证不会有重复的请求。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <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()
            //修改标识变量的值
            isSending = true;
            x.open("GET",'http://127.0.0.1:4000/delay')
            x.send()
            x.onreadystatechange = function(){
                if(x.readyState === 4){
                    //修改标识变量
                    isSending = false
                }
            }
        }

        //abort
        btns[1].onclick = function(){
            x.abort()
        }
    </script>  

</body>
</html>

AXIOS

简介

Axios是一个基于promise 的 HTTP 库(类似于jQuery的Ajax,用于HTTP请求),可以用在浏览器和 node.js中(既可以用于客户端也可以用于node.js编写的服务端)。

axios(ajax i/o system)不是一种新技术,本质上也是对原生XHR(XMLHttpReques)的封装,只不过它是基于Promise的,是Promise的实现版本,符合最新的ES规范。

特性

  • 从浏览器创建 XMLHttpRequests请求

  • 从node.js创建http请求

  • 支持 Promise API

  • 拦截请求和响应,比如:在请求前添加授权和响应前做一些事情。

  • 转换请求数据和响应数据,比如:进行请求加密或者响应数据加密。

  • 取消请求

  • 自动转换JSON数据

  • 客户端支持防御XSRF

Axios的基础用法(get、post、put 等请求方法)

  • get:一般用于获取数据

  • post:一般用于提交数据(表单提交与文件上传)

  • patch:更新数据(只将修改的数据推送到后端(服务端))

  • put:更新数据(所有数据推送到服务端)

  • delete:删除数据

GET方法

  • 方式一:请求别名的使用 axios.get(url,[,config])用于获取数据

1、如果不带有参数,如下:

<script>
import axios from "axios";
export default {
  name: "HelloWorld",
  created() {
    axios
      .get("/data.json")
      .then((result) => {
        // result不是直接的返回结果
        console.log("数据:",result);
        // result.data才是真正的返回结果
        console.log("真正的数据:",result.data);
      })
      .catch((err) => {
        console.log(err);
      });
  },
};
</script>

2、如果带有参数,如下:

<script>
  import axios from "axios";
  export default {
    name: "HelloWorld",
    created() {
      // 第一种方式:将参数直接写在url中
      // 向给定ID的用户发起请求
      axios
        .get("/data.json?id=5")
        .then((result) => {
          // 处理成功情况
          console.log(result);
        })
        .catch((err) => {
          // 处理错误情况
          console.log(err);
        });
       
 
      // 第二种方式:将参数直接写在params中
      axios
        .get("/data.json", {
          //带参数时  ————若无参数时直接省略params对象不写
          params: {
            id: 5,
          },
        })
        .then((result) => {
          // result不是直接的返回结果
          console.log("数据:", result);
          // result.data才是真正的返回结果
          console.log("真正的数据:", result.data);
        })
        .catch((err) => {
          console.log(err);
        });
 
      // 支持async/await用法
      // axios 是一个基于 promise 网络请求库, 这意味着, 你必须使用 ES6 的 then() 或者 ES8 的 async/await 来处理 Promise 实例对象。
      // 注意: 由于async/await 是ECMAScript 2017中的一部分,而且在IE和一些旧的浏览器中不支持,所以使用时务必要小心。
 
      async function getUser() {
        try {
          const response = await axios.get("/user?ID=12345");
          console.log(response);
        } catch (error) {
          console.error(error);
        }
      }
    },
  };
</script>
  • 方式二:通过向axios传递相关配置来创建请求

1、r如果不带参数,如下:

<script>
import axios from "axios";
export default {
  name: "HelloWorld",
  created() {
    axios({
      method: "get",
      url: "/data.json"
    }).then((res) => {
      // result不是直接的返回结果
      console.log("数据:", result);
      // result.data才是真正的返回结果
      console.log("真正的数据:", result.data);
    });
  },
};
</script>

2、如果带有参数,如下:

<script>
import axios from "axios";
export default {
  name: "HelloWorld",
  created() {
    axios({
      method: "get",
      url: "/data.json",
      //带参数时  ————若无参数时直接省略params对象不写
      params: {
        id: 5,
      },
    }).then((result) => {
      // result不是直接的返回结果
      console.log("数据:", result);
      // result.data才是真正的返回结果
      console.log("真正的数据:", result.data);
    });
  },
};
</script>

POST方法

  • post请求常用的数据请求格式有三种:

1、Content-Type : application/x-www-form-urlencoded。

ajax默认的数据格式。请求体中的数据会以json字符串的形式发送到后端。

2、Content-Type : application/json ; charset=utf-8。

axios默认的数据格式。请求体中的数据会以普通表单形式(键值对)发送到后端。

3、Content-Type : multipart/form-data 。

它会将请求体的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件。

  • 方式一:请求别名的使用 axios.post(url, [ , data [ , config]])用于发送数据 ’data’对象是作为请求主体被发送的数据

1、axios发送post无参请求,如下:

<script>
import axios from "axios";
export default {
  name: "HelloWorld",
  created() {
    //把get无参请求的get改为post即可
    axios.post("/data.json").then(res=>{
      console.log(res)
    });
  },
};
</script>

2、axios发送post有参请求,两种传参形式,如下:

i. 查询字符串形式

<script>
import axios from "axios";
export default {
  name: "HelloWorld",
  created() {
    //发送post请求携带参数,直接使用"uname=dingding&upwd=123456"
    axios.post("/data.json", "uname=dingding&upwd=123456").then(res=>{
      console.log(res)
    });
  },
};
</script>

ii.对象形式

<script>
import axios from "axios";
export default {
  name: "HelloWorld",
  created() {
    //发送post请求携带参数,这种传参方式后台得使用requestBody处理
    axios.post("/data.json", {uname:"dingding",upwd:123456}).then(res=>{
      console.log(res)
    });
  },
};
</script>
  • 方式二:通过向axios传递相关配置来创建请求

<script>
import axios from "axios";
export default {
  name: "HelloWorld",
  created() {
     let data = {uname:"dingding",upwd:123456};
     axios({
       method:'post',
       url:'/data.json',
       // 与get请求使用params不同的是,post请求使用data属性
       data:data
     }).then(res=>{
       console.log(res)
    })
  },
};
</script>

Express框架

简介

Express 是一个流行的 Node.js 框架,为开发者提供了简洁的 API,用于处理 HTTP 请求、响应,以及管理中间件、路由和错误处理。Express 简化了构建 RESTful API、Web 应用程序和微服务的过程。

创建基本 Express 应用

创建一个 app.js 文件:

const express = require('express');
const app = express();
 
// 定义路由
app.get('/', (req, res) => {
  res.send('Hello, World!');
});
 
// 启动服务器
app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

运行 app.js 文件后,将拥有一个在端口 3000 上运行的 Web 服务器。

Express 的主要功能

路由(Routing)

路由是指定义应用程序端点(URI)及如何响应客户端请求的方法。在 Express 中,路由使用方法如 app.get(), app.post(), app.put(), 和 app.delete() 等,分别对应 HTTP 的请求方法。

路由的使用示例代码:

const express = require('express');
const app = express();
 
// GET 请求的路由
app.get('/', (req, res) => {
  res.send('Hello World!');
});
 
// POST 请求的路由
app.post('/login', (req, res) => {
  // 处理登录逻辑
});
 
app.listen(3000, () => {
  console.log('App listening on port 3000');
});

上述例子中当用户发送 GET 请求至根路径 '/' 时,服务器会响应 'Hello World!'。类似地,当用户发送 POST 请求至 '/login' 路径时,服务器会处理登录逻辑。

获取请求报文参数:

在 Express 中,可以通过 req.params、req.query 和 req.body 来获取请求参数:

// 路由参数
app.get('/user/:id', (req, res) => {
  const userId = req.params.id; // 获取路由参数
});
 
// 查询参数
app.get('/search', (req, res) => {
  const query = req.query.q; // 获取查询参数
});
 
// 请求体参数
app.post('/login', (req, res) => {
  const username = req.body.username; // 获取 POST 请求体参数
});

在上述例子中,req.params.id 用于获取路由参数,req.query.q 用于获取查询参数,req.body.username 用于获取 POST 请求体参数。


AJAX
http://localhost:8090//archives/ajax
作者
文希希
发布于
2024年10月27日
许可协议