Ajax

Ajax介绍

AJAX是异步的JavaScript和XML(Asynchronous JavaScript And XML)。简单点说,就是使用 XMLHttpRequest 对象与服务器通信。 它可以使用JSON,XML,HTML和text文本等格式发送和接收数据。AJAX最吸引人的就是它的“异步”特性,也就是说它可以在不重新刷新页面的情况下与服务器通信,交换数据,或更新页面。

可以使用AJAX最主要的两个特性做下列事:

  • 在不重新加载页面的情况下发送请求给服务器。
  • 接受并使用从服务器发来的数据。

0x01 怎样发起http请求

//创建一个XHR对象
var httpRequest = new XMLHttpRequest();

发送一个请求后,你会收到响应。你要告诉XMLHttp请求对象是由哪一个js函数处理响应,在设置了对象的 onreadystatechange属性后给他命名,当请求状态改变时调用函数。

httpRequest.onreadystatechange = nameOfTheFunction;

要注意的是,函数名后没有参数,因为把一个引用赋值给了函数,而不是真正的调用了它。 此外,如果不使用函数名的方式,你还可以用JavaScript的匿名函数响应处理的动作,就像下面这样:

httpRequest.onreadystatechange = function(){
    // Process the server response here.
};

接下来,声明当你接到响应后要做什么,要发送一个实际的请求,通过调用HTTP请求对象的 open()send() 方法,像下面这样:

httpRequest.open('GET', 'http://www.example.org/some.file', true);
httpRequest.send();

data = "something....";
httpRequest.open('POST', 'http://www.example.org/some.file', true);
httpRequest.send(data);
  • open() 的第一个参数是HTTP请求方法 - 有GET,POST,HEAD以及服务器支持的其他方法。 保证这些方法一定要是大写字母,否则其他一些浏览器(比如FireFox)可能无法处理这个请求。
  • 第二个参数是你要发送的URL。由于安全原因,默认不能调用第三方URL域名。 确保你在页面中使用的是正确的域名,否则在调用 open() 方法是会有 “permission denied” 错误提示。一个容易犯的错误是企图通过 domain.tld 访问网站, 而不是使用 www.domain.tld
  • 第三个参数是可选的,用于设置请求是否是异步的。如果设为 true (默认值),即开启异步,JavaScript就不会在此语句阻塞,使得用户能在服务器还没有响应的情况下与页面进行交互。

send() 方法的参数可以是任何你想发送给服务器的内容,如果是 POST 请求的话。发送表单数据时应该用服务器可以解析的格式,像查询语句:

"name=value&anothername="+encodeURIComponent(myVar)+"&so=on"

或者其他格式, 类似 multipart/form-data,JSON,XML等。

如果你使用 POST 数据,那就需要设置请求的MIME类型。比如,在调用 send() 方法获取表单数据前要有下面这个:

httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

0x02 处理服务器响应

在发送请求时,提供的JavaScript函数名负责处理响应:

httpRequest.onreadystatechange = nameOfTheFunction;

这个函数应该做什么?首先,函数要检查请求的状态。可以通过检查返回的状态码 200 OK 来判断AJAX是否成功

if (httpRequest.status === 200) {
    // Perfect!
} else {
    // There was a problem with the request.
    // For example, the response may have a 404 (Not Found)
    // or 500 (Internal Server Error) response code.
}

在检查完请求状态和HTTP响应码后, 就可以用服务器返回的数据做任何你想做的了。你有两个方法去访问这些数据:

  • httpRequest.responseText – 服务器以文本字符的形式返回
  • httpRequest.responseXML – 以 XMLDocument 对象方式返回,之后就可以使用JavaScript来处理

注意上面这一步只在发起异步请求时有效(即 open() 的第三个参数未特别指定或设为 true)。如果发起的是同步请求则不必使用函数,但是非常不推荐这样子做,它的体验很糟糕。

0x03 简单的列子

前端使用Ajax发送用户名和密码

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>ajax and node study</title>
    </head>
    <body>
        <h3>你好,欢迎访问</h3>
        <p>请输入您的用户名和密码</p>
        <form name="myForm">
            <input name="username" id="username" type="text" style="display: flex;">
            <input name="passwd" id="passwd" type="password">
            <input id="submit" type="button" value="login" style="display: flex;">
        </form>
        <script>
            document.getElementById('submit').onclick = sendMsg;
            function sendMsg() {
                var username = document.getElementById('username').value;
                var passwd = document.getElementById('passwd').value;
                //创建一个xhr对象
                var xhr = new XMLHttpRequest();
                //开启访问  这里使用POST方法
                xhr.open('POST', 'http://localhost:8000');
                //发送数据
                xhr.send(`username: ${username} passwd: ${passwd}`);
                alert('已发送');
            }
        </script>
    </body>
</html>

后端代码

const http = require('http');
const fs = require('fs');
recv = ''
const server = http.createServer((req, res) => {
    //设置CORS头部允许从http://127.0.0.1:5500跨域请求http://localhost:8000
    res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500');
    req.on('data', (data) => {
        recv += data;
    });
    res.end(recv);
});
server.listen(8000);
console.log('访问 http://localhost:8000');

运行结果

image-20220425214616120

使用Ajax在浏览器中是默认不允许进行跨域访问的(若服务端未设置Access-Control-Allow-Orign头部),但值得注意的是,事实上服务端还是收到了来自客户端的数据了的,只是浏览器返回给用户一个CORS错误。

这里向服务器跨域发送,发现在浏览器会报错

image-20220425215108667

但服务器依旧是收到了来自客户端的数据

image-20220425215150697

0x04 小结

Ajax在异步处理中占据着举足轻重的地位,向在XSS中可向自己的服务器发送相关的数据等等。当然,有关XMLHttpRequest的更多用法这里还未提及,需要自己去探索