Ajax笔记
[异步的js和xml]
- 它的作用就是通过js向服务器发送请求来加载数据
- xml是早期AJAX使用的数据格式:
<student>
<name>孙悟空</name>
</student> - 目前数据格式都使用json
{"name" :"孙悟空"}
- 发送请求可以选择的方案:
- XMLHTTPRequest(xhr)
- Fetch
- Axios
- 三者的关系
Rest风格
什么是rest?
- REpresentational State Transfer
- 表示层状态的传输
- Rest实际上就是一种服务器的设计风格,它的主要特点就是服务器只返回数据
- 服务器和客户端传输数据时通常会使用JSON作为数据格式
- 请求的方法:
- GET 加载数据
- POST 新建或添加数据
- PUT 添加或修改数据
- PATCH 修改数据
- DELETE 删除数据
- OPTION 由浏览器自动发送,检查请求的一些权限
- API(接口)对于同个对象的操作,路由路径要统一
- GET /user
- POST /user
- DELETE /user/:id
- 对比
- 之前的服务器只能有两种路由(get&post),只能通过路由路径来区分不同功能
- 之前的服务器将数据渲染进页面,再将页面返回
为什么要用rest?
- 之前编写的服务器都是传统的服务器,服务器的结构是基于MVC模式
- Model -- 数据模型
- View -- 视图,用来呈现
- Controller -- 控制器,复杂加载数据并选择视图来呈现数据
- 传统的服务器是直接为客户端返回一个页面
- 但是传统的服务器并不能适用于现在的应用场景
- 现在的应用场景,一个应用通常都会有多个客户端存在:web端,移动端(app),pc端
- 如果服务器直接返回html页面,那么服务器就只能为web端提供服务,其他类型的客户端还需要单独开发服务器,这样就提高了开发和维护的成本
如何解决这个问题?
传统的服务器需要做两件事情,第一个加载数据,第二个要将模型渲染进视图
解决方案就将渲染视图的功能从服务器中剥离出来,服务器只负责向客户端返回数据,渲染视图的工作由客户端自行完成
分离以后,服务器只提供数据,一个服务器可以同时为多种客户端提供服务,同时将视图渲染的工作交给客户端以后,简化了服务器代码的编写
postman
这是一个软件,通过它可以帮助向服务器发送各种请求,帮助我们测试API
CORS (跨域资源共享)
跨域请求
- 如果网站的完整的域名不相同则就是跨域
- 跨域需要检查三个东西:
- 协议
- 域名
- 端口号
- 三个只要有一个不同,就算跨域
- 当我们通过AJAX去发送跨域请求时,浏览器为了服务器的安全,会阻止JS读取到服务器的数据
- 解决方案
- 在服务器中设置一个允许跨域的响应头
Access-Control-Allow-Origin
- 允许那些客户端访问我们的服务器
- 在服务器中设置一个允许跨域的响应头
代码
app.use((req, res, next) => {
//设置响应头
res.setHeader("Access-Control-Allow-Origin", "*")
res.setHeader("Access-Control-Allow-Headers", "Content-type,Authorization")
res.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,PATCH")
next()
})
- Access-Control-Allow-Origin 设置指定值时只能设置一个
- Access-Control-Allow-Methods 允许的请求的方式
- Access-Control-Allow-Headers 允许传递的请求头
xhr
//创建一个xhr对象
const xhr = new XMLHttpRequest()
//设置响应体的类型,设置后会自动对数据进行类型转换
xhr.responseType="json"
//给xhr绑定一个事件:当xhr中数据加载完毕
xhr.onload = function () {
// xhr.status 表示响应状态码
if (xhr.status === 200) {
//读取响应信息
// xhr.response 表示响应信息-
//把返回的JSON字符串转换成JSON对象
//const result=JSON.parse(xhr.response)
const result=xhr.response
if(result.status==="ok"){
console.log(result.data)
}
}
}
// 设置请求的信息
xhr.open("get", "http://localhost:3000/students")
//向服务器发送请求
xhr.send()
fetch
fetch是xhr的升级版,采用的是Promise API,服务器返回的数据会封装到promise里
作用和AJAX是一样的,但是使用起来更加友好
fetch是原生js就支持的一种ajax请求的方式
示例1
fetch("http://localhost:3000/students", {
method: "post",
// 通过body去发送数据时,必须通过请求头来指定数据的类型
body: JSON.stringify({
}),
// application/x-www-form-urlencoded 表单的形式
headers:{"Content-type":"application/json"}
})示例2
fetch("http://localhost:3000/students")
.then((res) => {
if (res.status === 200) {
console.log("fetch返回的Promise中存储的值:",res)
//res===Response {type: 'cors', url: 'http://localhost:3000/students', redirected: false, status: 200, ok: true, …}
//res.json()可以用来读取json格式的数据,把json格式的数据作为返回值
return res.json()//{status: 'ok', data: ...}
} else {
throw new Error("加载失败")
}
})
.then((res) => {
if (res.status === "ok") {
console.log(res.data)
}
})
.catch((err) => {
console.log("出错了", err)
})终止请求功能
let abController
btn1.onclick=function(){
//创建AbortController对象
abController=new AbortController()
fetch("http://localhost:3000/test",{
//把ac对象配置进fetch里
signal:abController.signal
})
}
btn2.onclick=function(){
//调用ac.abort()终止请求
abController&&abController.abort()
}使用await写法
btn03.onclick=async()=>{
try{
const res=await fetch(.....)
const data=await res.json()
console.log(data)
}catch(e){
console.log("出错了",e)
}
}
jsonwebtoken
如何告诉服务器客户端的登录状态?
- rest风格的服务器是无状态的服务器,所以注意不要在服务器中存储用户的数据
- 服务器中不能存储用户信息,可以将用户信息发送给客户端保存
- 客户端每次访问服务器时,直接将用户信息发回,服务器就可以根据用户来识别用户的身份
- 但是如果将数据直接发送给客户端同样会有数据安全的问题,所以我们必须对数据进行加密,加密以后在发送给客户端保存,这样即可避免数据的泄露
- 在node中可以直接使用jsonwebtoken这个包来对数据进行加密
- jsonwebtoken(jwt) -> 通过对json加密后,生成一个web中使用的令牌
图解
示例
const jwt = require("jsonwebtoken")
const data = {
name: "猪猪",
age: 88,
gender: "男"
}
//expiresIn:表示token存活时间,用数值单位是秒,用字符串要加单位(例如1天就是1d)
const token = jwt.sign(data, "1234", { expiresIn: "1h" })//加密(数据,密钥,配置对象)
console.log(token)
try {
const decodeData = jwt.verify(token, "1234")//解密(令牌.密钥)
console.log(decodeData)
} catch (e) {
console.log("无效的token");
}
客户端在接收到token后,可以由以下方式发回:
headers:{
// "Bearer xxxxxx"
"Authorization":`Bearer ${token}`
}
本地存储
登录成功以后,为了保持用户的登录状态,需要将用户的信息存储到本地存储
所谓的本地存储就是指浏览器自身的存储空间,我们可以将用户的数据存储到浏览器内部
我们可以用浏览器的全局对象sessionStorage和 localStorage来实现
- sessionStorage 中存储的数据,浏览器所在页面一关闭就会丢失
- localStorage 不主动删除就会一直在
有以下方法:
- setItem() 用来存储数据
- getItem() 用来获取数据
- removeItem() 删除数据
- clear() 清空数据
不使用cookie的原因:
- 跨域一般浏览器不会自动发送cookie,跨域接发cookie存在安全问题
- 使用fetch发送的请求不会自带cookie,要配置起来操作繁琐
axios
- 在使用上与fetch的不同:
- 1.会自动转换json数据
- 在发请求无须在请求头指定所发送数据的类型,axios会自动识别数据设置请求头
- 在接收数据时,会把json字符串转换为json对象
- 2.使用axios发送请求,只有在响应状态码为2XX时才会走then,其余情况都会catch,这使得我们不用进行麻烦的响应状态码判断
示例
btn.onclick=function(){
axios({
method:'post',
url: "http://localhost:3000/students",
data: {
name:"珠珠",
age:16,
gender:"男",
address:"大山"
}
}).then((result)=>{
console.log(result)
}).catch((e)=>{
console.log("出错了",e)
})
}
重要配置
// baseURL 指定服务器的根目录(路径的前缀)
baseURL:"http://localhost:3000",
// 请求地址
url:"students",
// 请求方法,默认是get
method:"get",
// 指定请求头
// headers:{}
// 请求体
// data:"name=唐僧&age=16"
data: {
name: "唐僧",
age: 18,
gender: "男",
address: "女儿国"
},
// params 用来指定路径中的查询字符串
params:{
id:1,
name:"swk"
},
//timeout 过期时间
timeout:1000,
// 用来终止请求.用法与fetch相同
// signal
transformRequest:[function(data, headers){
// 可以在函数中对data和headers进行修改
data.name = "猪八戒"
//headers["Content-Type"] = "application/json"
return data
}, function(data, headers){
// 最后一个函数必须返回一个字符串,才能使得数据有效
return JSON.stringify(data)
}]
transformRequest
- 可以用来处理请求数据(data)
- 它需要一个数组作为参数,数组可以接收多个函数,请求发送时多个函数会按照顺序执行
- 函数在执行时,会接收到两个参数data和headers
默认配置
axios.defaults.baseURL = "http://localhost:3000"
axios.defaults.headers.common[
"Authorization"
] = `Bearer ${localStorage.getItem("token")}`
aixos实例
axios实例相当于是axios的一个副本,它的功能和axios一样
axios的默认配置在实例也同样会生效,但是我们可以单独修改axios实例的默认配置
法1:
const instance = axios.create({ baseURL:"http://localhost:4000"})
法2
const instance=axios.create()
instance.defaults.baseURL = "xxx"
响应拦截
axios的拦截器可以对请求或响应进行拦截,在请求发送前和响应读取前处理数据