手撕AJAX-从写下XML开始

121 阅读3分钟

手撕ajax

/*
 * @Author: Kongjingjing
 * @Date: 2022-09-20 10:34:14
 * @Description:
 */
const url = "/server";
let xhr = new xhrHttpRequest(); // 创建一个xhr对象 xhr
xhr.open("GET", url, true); // open方法创建一个http请求
xhr.responseType = "json"; //    请求头信息
xhr.setRequestHeader("Accept", "application/json");
// 发送请求
xhr.send(null);
xhr.onreadystatechange = function () {
  // 状态监听函数
  if (this.readyState !== 4) return;
  if (this.status === 200) {
    //请求成功
    handle(this.response);
  } else {
    // 请求失败
    console.log(this.statusText);
  }
};
//请求失败时的监听函数
xhr.onerror = function () {
  console.log(this.statusText);
};

promise封装

/**
 * @Author: Kongjingjing
 * @Date: 2022-09-20 11:11:34
 * @Description: promise封装ajax
 * @param {*} url 请求地址
 */
function getHttp(url) {
  let promise = new promise((reslove, reject) => {
    let xhr = new XMLHttpRequest(); // xml对象
    xhr.open("GET", url, true); // 建立http请求
    xhr.responseType = "json"; //    请求头信息
    xhr.setRequestHeader("Accept", "application/json");
    xhr.send(); // 发送请求
    xhr.onreadystatechange = function () {
      if (this.readyState !== 4) return;
      if (this.status === 200) {
        reslove(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
  });
  return promise;
}

原生ajax

ajax的本质

前端和服务器端的中间层(ajax引擎),前端将数据数据处理、校验放到ajax中处理 前端将请求交给ajax,ajax将请求发送到服务器端,服务器端进行处理,将返回结果交给ajax,最后通过js将结果显示页面

不需要刷新整个界面就可以对网页的某个部分进行更新 异步提交,不需要等待服务器端的响应,就可以发起第二次请求

get请求

实现get请求

利用http创建一个服务器端

const http = require("http");

const hostname = "127.0.0.1";
const port = 3000;

const server = http.createServer((req, res) => {
    res.end("Hello, World!\n");
});

server.listen(port, hostname, () => {
    console.log(`Server running at http://${hostname}:${port}/`);
});

创建一个前端简单demo

// html核心代码
<body>
    <h1>通过原生ajax获取数据</h1>
    <button id="btn1">点我获取数据</button>
    <h4>展示数据</h4>
    <div id="div1" class="div1"></div>
</body>
</html>

image.png 建立ajax请求

    <script>
        // 获取元素
        let btn = document.getElementById("btn1");
        // 监听鼠标的点击事件
        btn.addEventListener('click', function () {
            //创建一个ajax对象
            let xhr = new XMLHttpRequest();
            // 设置请求方法、url、是否异步
            xhr.open("get", "http://localhost:3000/", true);
            // 发送请求
            xhr.send();
            xhr.onreadystatechange = function () {
                // 获取xhr的所有数据
                console.log(xhr);
                //请求已经完成,响应已经就绪
                if (xhr.readyState === 4 && xhr.status === 200) {
                    // 获取响应的数据
                    console.log(xhr.responseText);
                    // 获取的响应数据展示在界面中
                    let div1 = document.getElementById("div1");
                    div1.innerHTML = xhr.responseText;
                }
            }
        })

    </script>

console.log(xhr);的结果

image.png

出现跨域

出现跨域,因为我的前端端口运行在5503端口,后端运行在3000,必然后出现跨域 解决方法:在服务器端设置允许的域

const server = http.createServer((req, res) => {
    //允许所有跨域
    // res.setHeader("Access-Control-Allow-Origin","*")
    // 允许指定域 我的前端项目的端口是5503
    res.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:5503")
    res.end("Hello, World!\n");
});

完成get请求

image.png

get实现一个ajax的步骤

            //创建一个ajax对象
            let xhr = new XMLHttpRequest();
            // 设置请求方法、url、是否异步
            xhr.open("get", "http://localhost:3000/", true);
            // 发送请求
            xhr.send();
            //处理基于响应的事件 onreadystatechange
            xhr.onreadystatechange = function () {
                //请求已经完成,响应已经就绪 判断状态
                if (xhr.readyState === 4 && xhr.status === 200) {
                   // todo
                }
            }

思考💡:readyState和status的区别

readyState和statu都是xhr的属性 readyState记录的是xhr运行时的状态,共有5个值,0~4 status记录的是http的状态码

如果只判断1个属性可以吗?

如果只判断readyState,服务器端是响应成功了,但是如果服务器端响应是存在错误的,那界面会出现不可预估的错误 如果只判断status,会出现弹窗3次的情况,分别对应的是readyState状态变化引起的,所以也不可以

post请求

原生ajax实现post请求

前端设置post请求代码,前端输入2个数,后端求和

// html核心代码
    <label>请输入数字1:</label>
    <input type="number" id="num1">
    <br>
    <label>请输入数字2:</label>
    <input type="number" id="num2">
    <br>
    <button id="btn1">点我获取数据</button>
    <h4>展示数据</h4>
    <div id="div1" class="div1"></div>

image.png

    // js核心代码
    <script>
        // 获取元素
        let btn = document.getElementById("btn1");
        // 监听鼠标的点击事件
        btn.addEventListener('click', function () {
            //创建一个ajax对象
            let xhr = new XMLHttpRequest();
            // 设置请求方法、url、是否异步
            xhr.open("post", "http://localhost:3000/", true);
            // 发送数据
            let postStr = document.getElementById("num1").value + ","+ document.getElementById("num2").value;
            //发送请求 
            xhr.send(postStr);
            xhr.onreadystatechange = function () {
                // 获取xhr的所有数据
                console.log(xhr);
                //请求已经完成,响应已经就绪
                if (xhr.readyState === 4 && xhr.status === 200) {
                    // 获取响应的数据
                    console.log(xhr.responseText);
                    // 获取的响应数据展示在界面中
                    let div1 = document.getElementById("div1");
                    div1.innerHTML = xhr.responseText;
                }
            }
        })

    </script>

实现效果:

image.png

后端server分析

const http = require("http");
const hostname = "127.0.0.1";
const port = 3000;
const server = http.createServer();
// 绑定请求事件
server.on("request", (req, res) => {
    let postData = '';
    // req.on 接受客户端的数据
    req.on('data', (chunk) => {
        postData += chunk;
    });
    // end事件,获取的数据在end中处理
    req.on('end', () => {
        // 设置跨域
        res.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:5503")
        let arr = postData.split(',');
        let sum = Number(arr[0]) + Number(arr[1]);
        // 操作返回值必须是string
        res.write(JSON.stringify(sum));
        res.end("结束");
    })
})
server.listen(port, hostname, () => {
    console.log(`Server running at http://${hostname}:${port}/`);
});

post请求传入的数据要通过server.on 来监听;要在req.on 中获取数据,在req.on('end',)做数据的处理操作,并且可以通过res.end()返回数据,且返回的数据必须是string 格式