前后端交互
本文是对前后端交互的简单介绍(ajax fetch 等知识)
一. ajax(async异步 js and xml)
流程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//1. 创建XHR
var xhr = new XMLHttpRequest()
//2. 配置过程
// open("请求方式","请求地址",是否异步)
//第三个参数 true为异步 效果为接收数据函数和之后的东西异步执行 即使接受没完成后面也可以继续执行
xhr.open("GET","...")
//3. send
xhr.send()
//4. 接收数据 注册一个事件
xhr.onreadystatechange = function (){
if(xhr.readyState === 4 && xhr.status === 200){ //解析完成 且 找到页面
console.log(xhr.responseText) //字符串
}else if(xhr.readyState === 4 && xhr.status === 404){
location.href = "404.html" //没有找到页面
}
}
xhr.onload = function(){
//不需要判断readyState了 走到4时再进来
if(xhr.status === 200){
...
}else if(xhr.status === 404){
...
}
}请求方式
get 获取数据
1
2
3
4
5
6
7
8
9
var xhr = new XMLHttpRequest()
xhr.open("GET","http://localhost:3000/users")
//xhr.open("GET","http://localhost:3000/users?username=xing") 查询参数
xhr.onload = function(){
if(xhr.status === 200){
console.log(JSON.parse(xhr.responseText))
}
}
xhr.send()post 提交数据
post username=kai&password=123
1
2
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")
xhr.send(`username=xing&password=123`)post {“username”:”kai”,”password”:”123”}
1
2
3
4
5
xhr.setRequestHeader("Content-Type","application/json")
xhr.send(JSON.stringify({
"username":"xing",
"password":"123"
}))put 更新数据
put 会全部覆盖
1
2
3
4
5
6
7
8
9
10
11
12
var xhr = new XMLHttpRequest()
xhr.open("PUT","http://localhost:3000/users/1") //, 1表示想修改谁
xhr.onload = function(){
if(/^2\d{2}$/.test(xhr.status)){
console.log(JSON.parse(xhr.responseText))
}
}
xhr.setRequestHeader("Content-Type","application/json")
xhr.send(JSON.stringify({
"username":"xing",
"password":"1234"
}))patch 部分修改
1
xhr.open("PATCH","http://localhost:3000/users/1") //, 1表示想修改谁
delete 删除信息
1
xhr.open("DELETE","http://localhost:3000/users/1") //, 1表示想删除谁
封装ajax
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
function queryStringify(obj) {
let str = ''
for (let k in obj) str += `${k}=${obj[k]}&`
return str.slice(0, -1)
}
// 封装 ajax
function ajax(options) {
let defaultoptions = {
url: "",
method: "GET",
async: true,
data: {},
headers: {},
success: function (res) {
console.log(res)
},
error: function (err) {
console.log(err)
}
}
let {url, method, async, data, headers, success, error} = {
...defaultoptions,
...options
}
// console.log(headers["Content-Type"])
if (typeof data === 'object' && headers["Content-Type"]?.indexOf("json") > -1) {
data = JSON.stringify(data)
// console.log(1111,data)
} else {
data = queryStringify(data)
// console.log(222,data)
}
// 如果是 get 请求, 并且有参数, 那么直接组装一下 url 信息
if (/^get$/i.test(method) && data) url += '?' + data
// 发送请求
const xhr = new XMLHttpRequest()
xhr.open(method, url, async)
xhr.onload = function () {
if (!/^2\d{2}$/.test(xhr.status)) {
error(
"错误状态码:" + xhr.status
)
return
}
// 执行解析
try {
let result = JSON.parse(xhr.responseText)
success(result)
} catch (err) {
error('解析失败 ! 因为后端返回的结果不是 json 格式字符串')
}
}
// 设置请求头内的信息
// console.log(headers)
for (let k in headers) xhr.setRequestHeader(k, headers[k])
if (/^get$/i.test(method)) {
xhr.send()
} else {
xhr.send(data)
}
}
1
2
3
4
5
6
7
8
9
10
11
ajax({
url: "http://localhost:3000/users/2",
data:{
username:"kai",
password:"123"
},
method:"put",
headers:{
"Content-Type":"application/json"
}
})
二. Promise
语法
promise是一个构造函数
1
2
3
4
5
6
7
8
9
10
11
var q = new Promise(function(resolve,reject){
//成功兑现
resolve()
})
q.then(function(){
//兑现承诺 这个函数被执行
...
}).catch(function(){
//拒绝承诺 这个函数被执行
...
})封装ajax
1
2
3
4
5
6
7
8
9
10
11
12
13
function pajax(options){
return new Promise ((resolve,reject) => {
ajax({
...options,
success(res){
resolve(res)
},
error(err){
reject(err)
}
})
})
}相当于嵌套改链式的感觉
判断多个执行结束
1
2
3
4
q1 q1 两个promise对象
Promise.all([q1,q2]).then(function(){
console.log("两个都结束")
})
三. async 和 await
语法
1
2
3
4
5
6
7
8
async function test(){ //async只影响内部
// 同步代码 无意义或 promise对象
//await console.log(111) //await 必须等它执行完再执行下一个
await pajax({ //本来因为promise异步在回调之前执行了222
...
})
console.log(222)
}作用 用同步写法来搞定异步 适合链式
四. fetch
目的
XMLHttpRequest 粗糙 fetch给它换壳儿
使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
fetch("地址").then(res => { //res包括状态码等
return res.json()
}).then(res=>{
console.log(res)
})
//传参
fetch(`...?username=${username}`).then(res => {
if(re.OK)
return res.json()
else{
//拒绝承诺
return Promise.reject({ //接受error
status:res.status,
statusText:res.statusText
})
}
}).then(res=>{
console.log(res)
}).catch(err=>{
console.log(err)
})
//post
fetch("...",{
method:"POST",
headers:{
"Content-Type","application/x-www-form-urlencoded"
},
body:"username=...&..." //格式要严格与上面headers对应
//json格式
headers:{
"Content-Type","application/json"
},
body:JSON.stringify({
username:"...",
...
})
}).then(res=>res.json()).then(res=>{
console.log(res)
})
五.cookie
语法
1
2
3
4
savebtn.onclick = function(){
document.cookie = "username=kai" //格式为键值对
document.cookie = "...=..."//一条一条存
}特点
内层的可以访问外层 外层不可访问内层
关闭浏览器就无了
调整过期时间
1
2
3
var date = new Date()
date.setMinutes(date.getMinutes()+1)
document.cookie = `username=kai;expires=${date.toUTCString}`//时区问题其他属性
- HttpOnly 设置该属性 前端将无法获取到该条cookie 后端可设置
删除cookie
思路:重新设置过期时间
六. jsonp(JSON with Padding)
简介
可以让网页从别的域名那获取资料 跨域读取数据
同源策略 :同域名 同端口号 同协议
不符合该策略的 浏览器为了安全 会组织请求
解决:
cors 由后端设置 Access-Control-Allow-Origin:
jsonp 前后端协作
原理:
动态创建script标签 src属性没有跨域限制
指向一个接口 接口返回的格式一定是 **( ) 函数表达式
1
2
3
4
5
6
7
8
9
10
11
function test(){
...
}
.onclick = function(){
var oscript = docunment.createElement("script")
oscript.src = "..."//未来地址
document.body.appendChild(oscript)
}
未来地址里内容必须是函数形式 需要后端配合
test(...)缺点
多次添加标签
1
2
3
oscript.onload = function (){
oscript.remove()
}只能get请求
七. 函数闭包
函数结果保留条件
函数有返回值
返回值必须是复杂类型
而且要赋值给外面的变量
1
2
3
4
5
6
7
8
9
10
11
12
13
function a(){
var name = "11"
console.log(name)
return {
a:1,
b:2
}
}
var obj1 = a() //函数执行完后name被回收 对象留下
var obj2 = a()
//obj1与obj2 不相同
//如果想回收
obj1 = null //对象没人管了 也被回收闭包
函数内部返回一个函数
被外界引用
这个函数就不会被销毁
内部函数所用到的外部函数的变量也不会被销毁
1
2
3
4
5
6
7
function outer(){
var name = "11"
return function(){ //函数内部返回一个函数
return name+"11" //内部函数所用到的外部函数的变量也不会被销毁
}
}
var fun = outer() //被外界引用优点 让临时变量永驻内存
缺点 内存泄漏 用完 fun = null;
例: 函数柯里化
1
2
3
4
5
6
7
8
9
10
function FetchContainer(url){ //url永驻内存了
return function(path){
return fetch(url+path)
}
}
var fetcha = FetchContainer("http://www.a.com")
fetcha("/aaa").then(res=>res.json()).then(res=>console.log(res))
fetcha("/bbb").then(res=>res.json()).then(res=>console.log(res))
//用完之后赋空
fetcha = null
前后端交互
http://kaikai12321.github.io/2022/12/25/前后端交互/