1. 什么是AJAX
原生生js中有两种通信,一个ajax,还有一个是fetch。
AJAX 并不是编程语言,是一种从网页访问 Web 服务器的技术。AJAX 代表异步 JavaScript 和 XML。
AJAX 使用浏览器内建的 XMLHttpRequest 对象从 web 服务器请求数据,在使用JavaScript 和 HTML DOM来显示或使用数据。Ajax 允许通过与场景后面的 Web 服务器交换数据来异步更新网页。这意味着可以更新网页的部分,而不需要重新加载整个页面。
2. AJAX如何工作?
- 网页中发生一个事件(页面加载、按钮点击)。
- 由 JavaScript 创建 XMLHttpRequest 对象。
- XMLHttpRequest 对象向 web 服务器发送HttpRequest请求。
- 服务器处理HttpRequest请求。
- 服务器将响应发送回网页。
- 由 JavaScript 读取响应。
- 由 JavaScript 更新页面。
3. XMLHttpRequest 对象详解
XMLHttpRequest 对象用于与服务器交互数据。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。
3.1 AJAX使用步骤
所有现代浏览器都支持XMLHttpRequest 对象。XMLHttpRequest 对象可用于在后台与 Web 服务器交换数据。这意味着可以更新网页的部分内容,而无需重新加载整个页面。
1. 创建 XMLHttpRequest 对象的语法:
var 实例化对象名 = new XMLHttpRequest();
var xhr = new XMLHttpRequest();
2. 定义回调函数。回调函数是作为参数传递给另一个函数的函数。在这种情况下,回调函数应包含响应准备就绪时要执行的代码。
xhr.onload = function() {
// 当响应准备就绪时要做什么
}
3. 发送请求。向服务器发送请求,使用 XMLHttpRequest 对象的 open()
和 send()
方法。
案例:
xhr.open("GET", "http://localhost:4000");
xhr.send();
3.2 跨域访问(Access Across Domains)
出于安全原因,现代浏览器一般不允许跨域访问。但是可以使用跨域的,可以把跨域写入响应头中。
跨域访问书写语法:响应对象.writeHead(响应码,{跨域设置})
案例:
// 引入http
const http = require("http");
// 创建一个服务对象,req:请求对象, res:响应对象
http.createServer(function (req, res) {
// 编写响应头,200时成功码,
res.writeHead(200, {
"Access-Control-Allow-Origin": "*"
})
res.end("a");
}).listen(process.env.PORT);//侦听来访问该端口的请求
"Access-Control-Allow-Origin":"*" :响应标头指定了该响应的资源是否被允许与给定的来源(origin)共享。
"Access-Control-Allow-Methods":"*" :允许所有方法跨域。
"Access-Control-Allow-Headers":"*" :允许所有标头跨域。
3.3 XMLHttpRequest 对象的属性
属性 | 描述 |
onload | 定义接收到(加载)请求时要调用的函数。使用 XMLHttpRequest 对象时,可以定义一个回调函数,以便在请求收到答复时执行。 |
onreadystatechange | 定义当 readyState 属性发生变化时调用的函数。 |
readyState(重点) | 保存 XMLHttpRequest 的状态。每当readyState 发生变化时就会调用 onreadystatechange 函数。
|
responseText | 是服务器响应属性,以字符串形式返回响应数据。 |
responseXML | 是服务器响应属性,以 XML 数据返回响应数据。 |
status(重点) | 返回请求的状态号
|
statusText | 返回状态文本(比如 "OK" 或 "Not Found") |
status状态码详解:xhr.status 是 XMLHttpRequest 对象的一个属性,用于获取服务器返回的 HTTP 状态码。HTTP 状态码是服务器在响应客户端请求时返回的三位数字代码,用于表示请求的处理结果。以下是常见状态码分类及其含义:
1. 1xx(信息性状态码):表示服务器已经接收到请求,并且正在处理,这类状态码通常不常用。
100 Continue:服务器已经接收到请求的初始部分,客户端应继续发送剩余部分。
2. 2xx(成功状态码):表示请求已经成功被服务器接收、理解并处理。
200 OK:请求成功,服务器已经返回请求的数据。
201 Created:请求成功,并且服务器创建了新的资源。
204 No Content:请求成功,但响应中没有返回任何内容。
3. 3xx(重定向状态码):表示需要客户端采取进一步的操作才能完成请求,通常用于重定向。
301 Moved Permanently:请求的资源已被永久移动到新的 URL。
302 Found:请求的资源临时移动到新的 URL。
304 Not Modified:客户端发送了带条件的请求,服务器告知客户端资源未修改,可使用缓存。
4. 4xx(客户端错误状态码):表示客户端的请求存在错误,服务器无法处理。
400 Bad Request:服务器无法理解客户端的请求,通常是请求格式错误。
401 Unauthorized:请求需要用户进行身份验证。
403 Forbidden:服务器理解请求,但拒绝执行该请求。
404 Not Found:服务器找不到请求的资源。
5. 5xx(服务器错误状态码):表示服务器在处理请求时发生错误。
500 Internal Server Error:服务器内部发生错误,无法完成请求。
502 Bad Gateway:服务器作为网关或代理,从上游服务器收到无效响应。
503 Service Unavailable:服务器暂时无法处理请求,通常是由于服务器过载或维护。
3.4 XMLHttpRequest 对象的方法
方法名 | 描述 |
new XMLHttpRequest() | 创建新的 XMLHttpRequest 对象。 |
abort() | 取消当前请求。 |
getAllResponseHeaders() | 是服务器响应方法,从服务器返回所有头部信息。 |
getResponseHeader() | 是服务器响应方法,从服务器返回特定的头部信息。 |
open(method, url, async, user, password) | 设置请求访问服务器的各种参数。 参数:
|
send() | 是向服务器发送请求的方法。该方法无参数用于 GET 请求。 |
send(string) | 是向服务器发送请求的方法。该方法有参数用于 POST 请求。 |
setRequestHeader(header,value) | 向请求添加 HTTP 头部。将标签/值对添加到要发送的标头。 参数:
|
3.4.1 open()方法中的参数method请求类型详解
- GET
- POST:主要用于向服务端发送消息,发送的内容通过send发送,可以发送文本、二进制流、大二进制流(Blob)、FormData、文档。可以接收消息,不会调用缓存,POST发送时同域情况下也会携带cookie,跨域时需要主动携带cookie。POST是先发起请求头,然后再发起消息体。
- PUT:目的是表意,向服务器添加数据,和post作用相同。
- DELETE:目的是表意,向服务器提交删除数据,和post作用相同。
- OPTIONS :在使用POST、PUT、DELETE跨域时都会触发。
使用非GET和POST,跨域需要服务器同意,因为Method也需要处理跨域。
3.4.2 请求头和响应头
<!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>
<body>
<script>
请求头和响应头:
请求头必须写在open之后,send之前
var xhr=new XMLHttpRequest();
xhr.addEventListener("load",loadHandler);
// xhr.open("GET","http://localhost:4000");
xhr.open("POST","http://localhost:4000");
请求头写法单词首字母大写,单词直接使用-分割,如果是自定义请求头使用X-开头
// xhr.setRequestHeader("Content-Type","application/json")
xhr.setRequestHeader("X-Cookie",localStorage.age);
xhr.send("aaa");
function loadHandler(e){
// console.log(xhr.response);
// 获取所有的响应头
console.log(xhr.getAllResponseHeaders());
console.log(xhr.getResponseHeader("x-name"));
}
</script>
</body>
</html>
1. 请求头的注意事项:
- 请求头必须写在open之后,send之前。使用setRequestHeader()方法设置请求头。
- 请求头写法单词首字母大写,单词直接使用-分割,如果是自定义请求头使用X-开头。
-
例如:setRequestHeader("Content-Type","application/json")这行代码的作用是告诉服务器发送的请求体中包含的是 JSON 格式的数据,这样服务器才能正确地解析这些数据。
2. 请求标头中的属性重点详解Content-Type:
Content-Type:指定请求体的内容类型,用于告知服务器请求体的数据类型(如表单数据、JSON数据等)。
Content-Type的属性值可以是以下类型:
- text/plain:纯文本类型,不包含任何格式控制字符,通常用于传输普通文本数据。
- text/html:HTML文档类型,用于传输HTML格式的网页内容。
- application/json:JSON数据类型,用于传输结构化的JSON数据。
- application/xml:XML数据类型,用于传输结构化的XML数据。
- multipart/form-data:用于通过HTTP POST方法传输表单数据,支持传输文件和文本数据,常用于文件上传。
- application/x-www-form-urlencoded:用于通过HTTP POST方法传输表单数据,将表单字段以URL编码的形式包含在请求体中。
- image/jpeg、image/png、image/gif:图片类型,用于传输图片文件的内容。
- application/octet-stream:二进制数据流类型,表示不属于其他已知类型的任意二进制数据,例如传输文件时常用的类型。
其它属性如图所示:
3. 响应头的注意事项:
- 获取所有的响应头使用getAllResponseHeaders()方法。
属性如图所示:
4. timeout超时
timeout是一个无符号长整型数,代表着一个请求在被自动终止前所消耗的毫秒数。默认值为 0,意味着没有超时。
案列:
// timeout超时
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", loadHandler);
xhr.addEventListener("timeout", timeoutHandler);
xhr.open("PUT", "http://localhost:4000");
如果1毫秒之后服务器还没有返回数据就算超时
xhr.timeout = 1;
xhr.send();
function loadHandler(e) {
console.log(xhr.response);
}
function timeoutHandler(e) {
// console.log(e);
断开xhr
xhr.abort();
// 断开后重新调用ajax,3次
}
超时过后会得到一个 ProgressEvent事件。
解决超时的方法:使用abort();断开请求,断开后重新调用ajax3次。
5. 服务器与客户端最简单的AJAX通信
1. 创建server文件夹。
2. 在集成终端中执行npm init -y 初始得到package.json文件。
3. 编写package.json文件。
{
"name": "serverzixie",
"version": "1.0.0",
"main": "server.js",
"scripts": {
"start": "cross-env PORT=4000 nodemon"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"nodemon": "^3.1.4",
"cross-env": "^7.0.3"
}
}
4.在集成终端中执行npm i 。
5. 编写server.js文件并在集成终端中使用npm start启动服务。
// 引入http
const http = require("http");
// 创建一个服务对象,req:请求对象, res:响应对象
http.createServer(function (req, res) {
// 编写响应头,200时成功码,
res.writeHead(200, {
"Access-Control-Allow-Origin": "*"
})
res.end("a");
}).listen(process.env.PORT);//侦听来访问该端口的请求
6. 编写前端发送请求的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>
<body>
<script>
// 创建一个
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", loadHandler);
xhr.open("GET", "http://localhost:4000");
xhr.send();
function loadHandler(e) {
console.log(xhr.response);
}
</script>
</body>
</html>
7. 查看效果。
6. 完整的服务端编写
6.1 服务端连接数据库MySql-完善数据库查询代码
在 5 的代码的基础上继续编写代码
1. 在server文件夹新创建一个SQL.js的文件。
2. 重新编写package.json文件。
{
"name": "serverzixie",
"version": "1.0.0",
"main": "server.js",
"scripts": {
"start": "cross-env PORT=4000 nodemon"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"mysql": "^2.18.1", 自己的mysql是低版本使用mysql 2.18.1
"mysql2": "^3.11.0" 自己的mysql是高版本使用mysql2 3.11.0
},
"devDependencies": {
"nodemon": "^3.1.4",
"cross-env": "^7.0.3"
}
}
3.在集成终端中执行npm i 。
4. 编写SQL.js文件。
引入MySQL模块
const mysql = require("mysql");
创建一个连接
const connect = mysql.createConnection({
host: "localhost",//IP地址
port: 3306, //端口号
database: "mysql_js",//连接的数据库名
user: "root",//数据库用户名
password: "123456" //数据库密码
})
console.log(connect);
5. 在 server.js中引入数据库。并使用 npm start命令开启服务。
引入数据库js文件
require("./MYSQL");
// 引入http
const http = require("http");
// 创建一个服务对象,req:请求对象, res:响应对象
http.createServer(function (req, res) {
// 编写响应头,200时成功码,
res.writeHead(200, {
"Access-Control-Allow-Origin": "*"
})
res.end("a");
}).listen(process.env.PORT);//侦听来访问该端口的请求
没有报红说明连接数据库成功
6.编写一个查询所有的实践案例:重新编写SQL.js文件
const mysql=require("mysql");
let connection=mysql.createConnection({
host:"localhost",
port:3306,
database:"game",
user:"root",
password:"123456"
})
connection.connect();
1.查询所有用户信息的函数
function selectAll(){
// 返回一个 Promise 对象,用于处理异步操作
return new Promise(function(resolve,reject){
// 执行 SQL 查询语句,查询 `user` 表中的所有记录
connection.query("SELECT * FROM `user` WHERE 1",function(err,result){
console.log(err,result);
})
})
}
2.导出查询所有的方法
exports.selectAll=selectAll;
重新编写server.js文件
1. 导入 自己编写的SQL.js 文件
const {selectAll}=require("./SQL.js");
2. 调用 selectAll 函数,执行查询操作
selectAll()
const http=require("http");
http.createServer(function(req,res){
res.writeHead(200,{
"Access-Control-Allow-Origin":"*",
"Access-Control-Allow-Methods":"*",
"Access-Control-Allow-Headers":"*",
"X-Name":"kwj",
"X-Age":30,
// 通过下面的内容设置自定义响应头可以被获取
"Access-Control-Expose-Headers":["X-Name","X-Age"]
})
res.end();
}).listen(process.env.PORT);
7.编写一个登录查询方法实践案例:重新编写SQL.js文件
const mysql=require("mysql");
let connection=mysql.createConnection({
host:"localhost",
port:3306,
database:"game",
user:"root",
password:"123456"
})
connection.connect();
1.查询所有的方法
function selectAll(){
// 返回一个 Promise 对象,用于处理异步操作
return new Promise(function(resolve,reject){
// 执行 SQL 查询语句,查询 `user` 表中的所有记录
connection.query("SELECT * FROM `user` WHERE 1",function(err,result){
// 若查询过程中出现错误
if(err){
// 将 Promise 的状态设置为已解决,并返回 null 表示查询失败
resolve(null);
}else{
// 若查询成功,将 Promise 的状态设置为已解决,并返回查询结果
resolve(result);
}
})
})
}
2.登录查询方法
function loginSelect(user,password){
// 返回一个 Promise 对象,用于处理异步操作
return new Promise(function(resolve,reject){
// 执行 SQL 查询语句,查询 `user` 表中满足条件的记录
connection.query("SELECT * FROM `user` WHERE `user`=? AND `password`=?",[user,password],function(err,result){
if(err){
// 若查询过程中出现错误
resolve(null);
}else{
// 若查询成功,将 Promise 的状态设置为已解决,并返回查询结果的第一个元素
resolve(result[0]);
}
})
})
}
1.导出查询所有的方法
exports.selectAll=selectAll;
2.导出登录查询的方法
exports.loginSelect=loginSelect;
重新编写server.js文件
// 1. 导入 自己编写的SQL.js 文件
// const {selectAll}=require("./SQL.js");
// 2. 调用 selectAll 函数,执行查询操作
// se