Ajax-concept, Http protocol, Ajax request and its common problems

Other AJAX knowledge
AJAX same-origin policy and cross-domain problem solutions - click here
Different ways of sending AJAX requests - click here

Ajax concept

The full name of AJAX is Asynchronous Javascript And XML, which is asynchronous JS and XML . AJAX can send an asynchronous request to the server in the browser, the biggest advantage: get data without refreshing . AJAX is not a new programming language, but a new way of combining existing standards.

XML : Extensible Markup Language . XML was designed to transmit and store data . XML is similar to HTML, the difference is that there are predefined tags in HTML, but there are no predefined tags in XML, and all of them are custom tags, which are used to represent some data. (Currently replaced by JSON)

Advantages and disadvantages of Ajax

advantage:

  • It is possible to communicate with the server side without refreshing the page.
  • Allows you to update parts of the page content based on user events.

shortcoming:

  • No browsing history, no rewinding.
  • There is a cross domain issue (same origin).
  • SEO unfriendly (can't find it in source code).

HTTP protocol

The full name of HTTP is hypertext transport protocol ( Hypertext Transfer Protocol ), which specifies the rules for mutual communication between browsers and World Wide Web servers.

request message

Request line : POST /URL HTTP协议版本
Request header :

Host:值

Cookie: 值

Content-type:值

User-Agent:值Etc. Empty
line :
request body : if it is a GET request body, it is empty, if it is a POST, it may not be empty
Please add a picture description

response message

Response line : HTTP协议版本 响应状态码 响应状态字符串
Response headers :

Content-type:值

Content-length:值

Content-encoding:值Etc. Empty
line :
Response body : HTML syntax content
Please add a picture description

Ajax case preparation

express basic use

First download node and configure the node environment, and then enter it in the vscode terminal npm i express. If there is an error, you can try to run vscode with the administrator and try again. If it still doesn’t work, find the location of the node folder and find the node_cache node_global node_modulesthree files separately –> Properties –> Security –> Change permissions to full control.

It can be installed globally, that is, in the root directory of node.jsnpm i express -g

create a server

Create a new js file in the current directory (not necessarily in the root directory of the express installation), and then enter the terminal --> current directory --> input to node 文件名start the service

Please add a picture description

  • You can use nodemon to save and automatically restart

    Install nodemon:npm install -g nodemon

    Use: Enter in the current directory terminalnodemon 文件名

    This way you don't have to restart the service every time you make a change.

    Note: If an error is reported, enter npx nodemon 文件名and try again

Send an AJAX request

GET request

Click the button to display the response body in the div: click the button to send an AJAX request to the server, and then take the response body and put it in the div.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      #result {
      
      
        width: 200px;
        height: 100px;
        border: solid 1px pink;
      }
    </style>
  </head>
  <body>
    <button>点击发送请求</button>
    <div id="result"></div>

    <script>
      //获取button元素
      const btn = document.querySelector("button");
      const result = document.querySelector("#result");
      btn.addEventListener("click", function () {
      
      
        //1.创建对象
        const xhr = new XMLHttpRequest();
        //2.初始化,设置请求的方法和url
        xhr.open("GET", "http://127.0.0.1:8000/server?a=1&b=2&c=3");
        //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 ,2开头都表示成功
            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>
  </body>
</html>

Set url parameters: 用?隔开,=赋值,&分隔
for example:http://127.0.0.1:8000/server?a=1&b=2&c=3

Server server.js file:

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

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

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

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

POST request

The mouse sends an AJAX request through the div, and then gets back the response body and puts it in the div.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      #result {
      
      
        width: 200px;
        height: 100px;
        border: solid 1px pink;
      }
    </style>
  </head>
  <body>
    <div id="result"></div>
    <script>
      const result = document.querySelector("#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=1&b=2&c=3");
        // xhr.send('a:1&b:2&c:3');
        // xhr.send('1232142412421312');
        //4.绑定事件
        xhr.onreadystatechange = function () {
      
      
          //判断服务端是否返回所有结果
          if (xhr.readyState === 4) {
      
      
            //判断响应是否成功
            if (xhr.status >= 200 && xhr.status < 300) {
      
      
              //处理服务端返回的结果
              result.innerHTML = xhr.response;
            }
          }
        };
      });
    </script>
  </body>
</html>

server.js:

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

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

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

//POST请求
app.post("/server", (request, response) => {
    
    
  //设置响应头 设置允许跨域
  response.setHeader("Access-Controll-Allow-Origin", "*");
  //设置响应
  response.send("HELLO AJAX POST");
});

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

JSON response

The server response body can also be set as a piece of data to send, but it cannot be written directly. It needs to be JSON.stringify(数据)converted into a JSON string

//可以接收任意类型的请求
app.all("/json-server", (request, response) => {
    
    
  //设置响应头 设置允许跨域
  response.setHeader("Access-Control-Allow-Origin", "*");
  response.setHeader("Access-Control-Allow-Headers", "*");
  //响应一个数据
  const data = {
    
    
    name: "haha",
  };
  //对对象进行字符串转换
  let str = JSON.stringify(data);
  //设置响应体
  response.send(str);
});

When the page gets the JSON string response body, it cannot be recognized, so it is necessary to convert the JSON string into a js object. There are two ways:

  • manual conversionJSON.parse(xhr.response)
  • automatic conversionxhr.responseType = 'json';
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      #result {
      
      
        width: 200px;
        height: 100px;
        border: solid 1px pink;
      }
    </style>
  </head>
  <body>
    <div id="result"></div>
    <script>
      const result = document.querySelector("#result");
      window.onkeydown = () => {
      
      
        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) {
      
      
              //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>

Problems with Ajax requests

IE caching problem

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

IE When your response body changes, it will not be updated, but cached. To solve this problem, the url of each request must be different. Then we will pass a parameter later, and the value is a timestamp (because the timestamp It is impossible to repeat. In this case, the browser will think that the url is different and will resend the request to solve the problem), which can solve the problem that IE cache does not update when the response body is changed .

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

Ajax request timeout and network exception handling

We cannot guarantee that the server can respond promptly and quickly. At this time, we can set a timeout for Ajax and then return a reminder to the user. When the network is abnormal, we can also return a reminder to improve the user experience.

The server writes a timer and sends the response body after 2 seconds

//延时响应
app.get("/delay", (request, response) => {
    
    
  //设置响应头 设置允许跨域
  response.setHeader("Access-Control-Allow-Origin", "*");
  //设置响应
  //服务端写个定时器,2秒后发送响应体过去
  setTimeout(() => {
    
    
    response.send("HELLO 延时响应");
  }, 2000);
});

Then when you click the button to send the request, you can set the timeout xhr.timeoutand timeout callback xhr.ontimeout, as well as the network exception callbackxhr.onerror

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>IE缓存问题</title>
    <style>
      #result {
      
      
        width: 200px;
        height: 100px;
        border: solid 1px pink;
      }
    </style>
  </head>
  <body>
    <button>点击发送请求</button>
    <div id="result"></div>
    <script>
      const btn = document.querySelector("button");
      const result = document.querySelector("#result");
      btn.addEventListener("click", () => {
      
      
        const xhr = new XMLHttpRequest();
        //超时设置 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>

Ajax manual cancel request

When the request has not been responded to after sending it, the request can be canceled manually, and a reminder can be returned when it is cancelled.

Set a timer to send the response body:

app.get('/cancel', (request, response) => {
    
    
    //设置响应头
    response.setHeader('Access-Control-Allow-Origin', '*');
    //设置响应体
    setTimeout(() => {
    
    !
        response.send('HELLO 请求已经被取消');
    }, 2000);
})

To cancel a request, use xhr.abort()the method, abort=abort.
There is a scope problem here. The solution is to define xhr outside and give a null, then assign the xhr instance, and then call the method. (Repeated assignment cannot be const)

<!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>
    <button>点击取消请求</button>
    <div id="result"></div>
    <script>
      const send = document.querySelectorAll("button")[0];
      const cancel = document.querySelectorAll("button")[1];

      let xhr = null;
      //发送请求
      send.onclick = function () {
      
      
        xhr = new XMLHttpRequest();
        xhr.open("GET", "http://127.0.0.1:8000/cancel");
        xhr.send();
      };
      //取消请求,abort方法
      cancel.addEventListener("click", function () {
      
      
        xhr.abort(); //先点send再点cancel不会报错,先点cancel报错
      });
    </script>
  </body>
</html>

Ajax repeated sending request problem

When the user frantically clicks a button, the browser will send the same request repeatedly, causing excessive pressure on the server. Solution: When the user sends a request, first check whether there is the same request before, if there is, cancel the previous request, and only respond to the last request (here is the idea of ​​anti-shake, review the anti-shake throttling click here place )

<script>
      const btn = document.querySelector("button");
      let xhr = null;
      //标识变量 是否正在发送请求
      let isSending = false;
      //发送请求
      btn.onclick = function () {
    
    
        //判断标识变量
        if (isSending) x.abort();
        xhr = new XMLHttpRequest();
        //修改标识变量的值
        isSending = true;
        xhr.open("GET", "http://127.0.0.1:8000/delay");
        xhr.send();
        xhr.onreadystatechange = function () {
    
    
          if (xhr.readyState === 4) {
    
    
            isSending = false;
          }
        };
      };
</script>

Guess you like

Origin blog.csdn.net/weixin_56498069/article/details/132170393