前端Ajax基础

137 阅读7分钟

AJAX简介

AJAX不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。就是异步的JS和XML。通过AJAX可以在浏览器像服务器发送异步请求。

AJAX优点

  1. 可以无需刷新页面与服务器端进行通信。页面请求数据的时候不需要刷新页面就能拿到想要的数据。
  2. 允许你根据用户事件来更新部分页面内容

AJAX缺点

  1. 没有浏览历史
  2. 存在跨域问题(同源)
  3. SEO不友好

AJAX的使用

HTTP

HTTP协议:协议详细规定了浏览器和万维网服务器之间相互通信的规则。 协议就是一种约定、一种规则。

HTTP主要是约定了两块的内容,一块是请求,一块响应。

请求

浏览器向服务端发送的内容称之为请求报文。请求行和头看Request Headers请求体from Data。如果请求是一个GET请求那么Query String Parameters会对请求的URL内容做一个解析 重点格式与参数

  1. 请求行

请求行包括三部分 :请求类型(GET,POST)、URL路径、HTTP版本

  1. 请求头

请求头:名字冒号空格加值。

  1. 空行

空行是空的但是必须有。

  1. 请求体

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

响应

服务器给客户端返回的结果称之为响应报文。响应头Response Headers响应体Response

  1. 响应行

响应行包括三部分 :协议版本、响应状态码、响应状态字符串。

  1. 响应头

响应头:名字冒号空格加值。

  1. 空行

空行是空的但是必须有。

  1. 响应体

主要的返回结果。里面是HTML内容。

XML简介

XML:可扩展标记语言。(HTML:超文本标记语言)它们都是由标签组成的。但是XML它是被设计用来传输和储存数据的,不同的是HTML中都是定义标签,而XML中没有定义标签,全都是自定义标签,用来表示一些数据。

使用AJAX发送GET请求

1.安装node.js 2.安装npm init --yes 3.安装npm i express 4.启动 node server.js (server.js是文件名)

创建server.js

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

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

// 3、创建路由规则
// require请求报文的封装
// response响应报文的封装
app.get('/server',(require,response)=>{
    // 设置响应头
    response.setHeader('Access-Control-Allow-Origin','*');  //设置允许跨域
    // 设置响应
    response.send("hello AJAX");
})
// 4. 监听端口启动服务
app.listen(8000,()=>{
    console.log("服务已经启动,8000,端口监听中...")
})

HTML页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    #result{
        width: 200px;
        height: 100px;
        border: solid #ccc 1px;
    }
</style>
<body>
    <button>点击发送请求</button>
    <div id="result"></div>
    <script>
        // 获取button元素
       const btn = document.getElementsByTagName('button')[0];
       const result = document.getElementById("result")
        // 绑定事件
        btn.onclick=function(){
            // 创建对象
            const xhr = new XMLHttpRequest();
            
            // 初始化, 设置请求的方法和URL
            // 设置URL参数
            xhr.open("GET","http://127.0.0.1:8000/server?a=100&b=200&c=300");
            // 发送
            xhr.send();
            // 事件绑定 作用是处理服务端返回来的结果
            // on 相当于when  当...时候
            // readystate 是xhr中的属性,有五个表示状态 0 1 2 3 4
            // 1表示open方法调用完毕   2表示send方法调用完毕  3表示服务端返回的部分结果   4表示服务端返回的所有结果
            // change本身是改变的意思,当改变的时候触发
            xhr.onreadystatechange=function(){
                // 判断当服务端返回所有的结果
                if(xhr.readyState===4){
                    // 判断响应的状态 比如200 404  403 500
                    // 响应状态码中2开头的都是响应成功
                    if(xhr.status>=200 && xhr.status<300){
                        // 响应成功就处理结果
                        // 处理结果包括四部分  行 头 空行 体
                        // 1、响应行
                        // console.log(xhr.status);  //响应状态码
                        // console.log(xhr.statusText);    //响应字符串
                        // console.log(xhr.getAllResponseHeaders());    //响应所有状态头
                        // console.log(xhr.response);    //响应状态体
                        // 设置result文本
                        result.innerHTML=xhr.response;
                    }else{

                    }
                }
            }

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

GET请求URL参数是直接在URL上拼接,但是在post请求的时候,参数在send()中设置

使用AJAX发送post请求

server.js

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

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

// 3、创建路由规则
// require请求报文的封装
// response响应报文的封装
app.get('/server',(require,response)=>{
    // 设置响应头
    response.setHeader('Access-Control-Allow-Origin','*');  //设置允许跨域
    // 设置响应
    response.send("hello AJAX");
});

//对应的post标识
app.post('/server',(require,response)=>{
    // 设置响应头
    response.setHeader('Access-Control-Allow-Origin','*');  //设置允许跨域
    // 设置响应
    response.send("hello AJAX");
});
// 4. 监听端口启动服务
app.listen(8000,()=>{
    console.log("服务已经启动,8000,端口监听中...")
})

HTML页面

<!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>
</head>
    <style>
        #result{
            width: 200px;
            height: 100px;
            border: tan solid 1px;
        }
    </style>
<body>
    <p >    实现需求,当我鼠标放到div里面,请求的数据放在我的div里面</p>
    <div id="result"></div>
    <script>
        //获取元素
        const result = document.getElementById("result");
        // 绑定事件
        result.addEventListener("mouseover",function(){
            // 创建对象
            const xhr= new XMLHttpRequest();
            // 初始化 设置请求类型和URL
            xhr.open("POST","http://127.0.0.1:8000/server");
            // 发送
            // xhr.send("a=100&b=200&c=300");   //post中发送请求的参数
            // 等同于
            xhr.send("a:100&b:200&c:300");   //post中发送请求的参数
            // 事件绑定
            xhr.onreadystatechange=function(){
                // 判断服务端响应回来的结果
                if(xhr.readyState===4){
                    // 判断响应状态  2开头的都是成功的
                    if(xhr.status>=200 && xhr.status<300){
                        // 请求成功就处理服务端返回的结果
                        result.innerHTML=xhr.response;
                    }else{

                    }
                }
            }
        }) 
    </script>

</body>
</html>

设置请求头信息 setRequestHeader

  1. Content-Type设置请求体里面的类型的。
  2. application/x-www-form-urlencoded请求体参数查询字符串。
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')

设置信息我们不光可以设置预定义的,也可以自定义

xhr.setRequestHeader('name','atxiaocai')

自定义过后会报错,这个时候我们需要在服务端的JS里面server.js设置一下

表示所有类型的头信息我都可以接受

 response.setHeader('Access-Control-Allow-Headers','*');  

这个时候还是会报错但是把server.js代码中post请求的标识换成all就不会出现报错了

all表示可以接收任意类型的请求

app.all('/server',(require,response)=>{
    // 设置响应头
    response.setHeader('Access-Control-Allow-Origin','*');  //设置允许跨域
    response.setHeader('Access-Control-Allow-Headers','*');  //表示所有类型的头信息我都可以接受
    // 设置响应
    response.send("hello AJAX");
});

AJAX--服务端响应JSON数据响应

server.js

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

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

// 3、创建路由规则
// require请求报文的封装
// response响应报文的封装
app.get('/server',(require,response)=>{
    // 设置响应头
    response.setHeader('Access-Control-Allow-Origin','*');  //设置允许跨域
    // 设置响应
    response.send("hello AJAX");
});

app.all('/server',(require,response)=>{
    // 设置响应头
    response.setHeader('Access-Control-Allow-Origin','*');  //设置允许跨域
    response.setHeader('Access-Control-Allow-Headers','*');  //表示所有类型的头信息我都可以接受
    // 设置响应
    response.send("hello AJAX");
});

app.all('/json-server',(require,response)=>{
    // 设置响应头
    response.setHeader('Access-Control-Allow-Origin','*');  //设置允许跨域
    response.setHeader('Access-Control-Allow-Headers','*');  //表示所有类型的头信息我都可以接受
    // 响应一个数据
    const data={
        name:"小太阳"
    }
    // 对对象进行字符串转换
    let str=JSON.stringify(data)
    // 设置响应
    response.send(str);   //send里面只能放字符串
});
// 4. 监听端口启动服务
app.listen(8000,()=>{
    console.log("服务已经启动,8000,端口监听中...")
})

HTML页面

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AJAX JSON</title>
</head>
<style>
    #result {
        width: 200px;
        height: 100px;
        border: tan solid 1px;
    }
</style>

<body>
    <p> 实现需求,在窗口下面按下键盘按钮,请求数据</p>
    <div id="result"></div>
    <script>
        // 获取div
        const result=document.getElementById("result")
        // 绑定键盘按下事件
        window.onkeydown=function(){
            // 向服务端发送请求 
            const xhr=new XMLHttpRequest();
             // 自动数据转换,借助xhr里面responseType
             xhr.responseType="json"
            // 调用open方法做一个初始化
            xhr.open("GET","http://127.0.0.1:8000/json-server")
            // 发送请求
            xhr.send();
            // 事件绑定
            xhr.onreadystatechange=function(){
                // 判断状态
                if(xhr.readyState===4){
                    // 判断状态码是不是大于等于200小于300
                    if(xhr.status>=200 && xhr.status<300){
                        // console.log(xhr.response);
                        // result.innerHTML=xhr.response;
                        // 手动数据转换
                        // let data=JSON.parse(xhr.response);
                        // result.innerHTML=data.name
                        // 自动数据转换,借助xhr里面responseType
                        result.innerHTML=xhr.response.name
                    }

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

如果是一个对象应该怎么取到值

// 响应一个数据
    const data={
        name:"小太阳"
    }
    // 对对象进行字符串转换
    let str=JSON.stringify(data)
    // 设置响应
    response.send(str);   //send里面只能放字符串
  // 手动数据转换
  let data=JSON.parse(xhr.response);
  result.innerHTML=data.name
  
    // 自动数据转换,借助xhr里面responseType
       xhr.responseType="json";  		//写在向服务器发送请求过后
  // 自动数据转换。
  result.innerHTML=xhr.response.name
  

AJAX ---IE缓存问题

什么是IE缓存问题,IE浏览器会对AJAX请求的结果做一个缓存,这样就会导致下一次去请求的时候,这个时候走的是本地的缓存,并不是服务器返回的最新数据,这样就会影响结果。

AJAX---IE缓存解决方法,给请求URL加上一个时间戳?t="+Date.now(),这样每次发送请求的时候URL就会不一样,这样就会重新去发新的请求而不是走本地缓存

xhr.open("GET","http://127.0.0.1:8000/ie?t="+Date.now());

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

我们不能保证服务端永远及时快速的响应,这个时候我们可以对AJAX做一个超时的设置,在请求超时和网络异常的情况下给用户提醒。

HTML页面

const btn = document.getElementsByTagName("button")[0];
const result = document.querySelector("#result");
btn.addEventListener("click", function () {
  const xhr = new XMLHttpRequest();
  // 超时设置  如果2秒之内还没有请求回来结果   就取消请求
  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;
          }
      }
  }
})

server.js页面

// 延时的服务
app.all('/delay',(require,response)=>{
    // 设置响应头
    response.setHeader('Access-Control-Allow-Origin','*');  //设置允许跨域
    response.setHeader('Access-Control-Allow-Headers','*');  //表示所有类型的头信息我都可以接受
    // 设置响应
    setTimeout(()=>{
        response.send("延迟响应");
    },3000)   //设置时间为3秒
   
});

AJAX取消请求

在发送请求过后,返回结果之前,手动取消请求。

只要调用abort方法就能手动取消

<button>发送请求</button>
<button>取消请求</button>
<script>
    const btns=document.querySelectorAll("button")
    let  xhr=null     //此处使用let   const的值不能够被修改
    btns[0].onclick=function(){
        const xhr=new XMLHttpRequest();
        xhr.open("GET","http://127.0.0.1:8000/delay");
        xhr.send();
    }
    btns[1].onclick=function(){
        xhr.abort()    //此处的xhr不在一个函数内,所以要在上面声明一下
    }
</script>

AJAX重复发送请求的问题

在向服务器发送请求的时候,如果重复性发送同一个请求,就会给服务器造成压力。

在向服务器发送请求的时候,看一下有没有相同的请求,如果有那就把之前的请求取消掉,然后发送新的请求。

新增代码改动

let isSending = false; //是否正在发送AJAX请求
// 判断标识变量
// 如果正在发送请求,则取消该请求创建一个新的请求
if (isSending) xhr.abort();
   // 修改标识码的值
isSending = true; //正在发送AJAX请求
 xhr.onreadystatechange = function () {
    // 判断请求是否完成
    if (xhr.readyState === 4) { //状态为4就请求完成
        // 修改标识变量
        isSending = false;
    }
}

整体代码

const btns = document.querySelectorAll("button")
let xhr = null; //此处使用let   const的值不能够被修改
let isSending = false; //是否正在发送AJAX请求
btns[0].onclick = function () {
    // 判断标识变量
    // 如果正在发送请求,则取消该请求创建一个新的请求
    if (isSending) xhr.abort();
    xhr = new XMLHttpRequest();
    // 修改标识码的值
    isSending = true; //正在发送AJAX请求
    xhr.open("GET", "http://127.0.0.1:8000/delay");
    xhr.send();
    // 在请求完成之后就应该还原成false
    xhr.onreadystatechange = function () {
        // 判断请求是否完成
        if (xhr.readyState === 4) { //状态为4就请求完成
            // 修改标识变量
            isSending = false;
        }
    }
}