前后端交互,http,ajax
前后端数据交互
1. 前后端通信的过程
前后端通信过程是在”请求-响应“中完成的
2. 概念解释
前端:浏览器端 客户端:只要能和服务器通信的 命令行工具: curl http:www.imooc.com 后端:服务器端
3. 前后端通信方式
使用浏览器访问网页: 在浏览器地址栏输入网址,按下回车
HTML标签: 浏览器在解析HTML标签的时候,遇到一些特殊的标签,会再次向服务器发送请求 link\img\script\iframe
Ajax和fetch:
HTTP协议
HyperText Transfer Protocol 超文本传输协议,协议详细规定了浏览器和万维网服务器之间互相通信的规则约定 超文本:原先一个个单一的文本,通过超链接将其联系起来。由原先的单一文本变成了可无线延伸、扩展的超级文本、立体文本
HTTP请求响应过程
HTTP报文
浏览器向服务器发送请求时,请求本身就是信息,叫请求报文 服务器向浏览器发送响应时传输的信息,叫响应报文
HTTP报文格式
请求 请求头 请求体 响应 响应头 响应体
GET请求没有请求体,数据通过请求头携带 POST请求有请求头,既可以在请求头中携带数据,也可以通过请求体携带数据 在html表单里就可以发送get请求和post请求
<form action="https://www.immoc.com" method = "get">
<input type="text" name="username" placeholder="用户名"/>
<input type="password" name="password" placeholder="密码"/>
<input type="submit" value="注册"/>
</form>
<form action="https://www.imooc.com" method="post">
<input type="text" name="username" placeholder="用户名"/>
<input type="password" name="password" placeholder="密码"/>
<input type="sumit" value="注册"/><!--POST请求-->
</form>
HTTP方法
浏览器发送请求时采用的方法,和响应无关 GET POST PUT DELETE 用于定义对于资源采取什么样的操作的,有各自的语义 GET 获取数据,获取资源(文件) POST 创建数据,注册 PUT 更新数据, 修改个人信息,修改密码 DELETE 删除数据,删除一条评论 查增改删 这些方法虽然有各自的语义,但是并不是强制性的
使用少量数据,可以使用GET请求,大量数据,使用POST请求 GET可以被缓存,POST不会被缓存 发送密码或其他敏感信息时不要使用GET,主要是避免直接窥屏或通过历史记录找到你的密码
HTTP状态码
定义服务器对请求的处理结果,是服务器返回的
状态码语义 100~199 代表请求已被接受,需要继续处理
200~299 代表成功
300~399 重定向
301 Moved Permanently
302 Move Temporarily
304 Not Modified
400~499 请求错误
404 Not Found
500~599 服务器错误
500 Internal Server Error
Ajax
XML
异步编程 XML
AJAX的特点
优点:无需刷新页面而与服务器端进行通信、
允许你根据用户事件来更新部分页面内容
缺点:没有浏览历史,不能回退,
存在跨域问题,
SEO不友好
AJAX的使用
请求报文
-
行 GET /POST 路径:url
-
头
Host: atguigu.com Cookie: name=guigu Content-type: application/x-www-form-urlencoded User-Agent: chrome 83
-
空行
-
体(对于GET请求,请求体为空;对于POST请求,请求体不为空)
username=admin&password=admin
响应报文
-
行 协议版本 响应状态码 响应字符串
-
头 Content-Type: text/html; charset=utf-8
Content-length: 2048
Content-encoding: gzip
-
空行
-
体
<html> <head> </head> <body> <h1> </h1> </body> </html>
查看报文
Express框架
初体验
//1.引入express
const express = require("express");
//2.创建应用对象
const app = express();
//3.创建路由规则
//request 是对请求报文的封装
//response 是对响应报文的封装
app.get('/',(request,response)=>{
response.send("hello,world!");
});
//4.监听端口启动服务
app.listen(8000,()=>{
console.log("服务已启动,8000端口监听中....");
})
发送请求
发送GET请求
GET请求没有请求体,数据通过请求头携带
另起一个js文件设置端口
//1.引入express
const express = require("express");
//2.创建应用对象
const app = express();
//3.创建路由规则
//request 是对请求报文的封装
//response 是对响应报文的封装
app.get('/server',(request,response)=>{
//设置响应头
response.setHeader("Access-Control-Allow-Origin",'*');
//设置响应体
response.send("hello,Ajax");
});
//4.监听端口启动服务
app.listen(8000,()=>{
console.log("服务已启动,8000端口监听中....");
})
在终端启动 node server.js
在script标签里面写的内容
//获取button元素
let btn = document.getElementsByTagName("button")[0];
//绑定事件
let result = document.getElementById("result");
btn.onclick = function(){
//1.创建对象
const xhr = new XMLHttpRequest();
//2.初始化 设置请求方法和url
xhr.open("GET","http://127.0.0.1:8000/server");
//3.发送
xhr.send();
//4.事件绑定 处理服务端返回的结果
// on 当什么的时候
// readystate 是 xhr 对象中的属性,表示状态 0 1 2 3 4
// 0表示未初始化 1表示open方法调用完毕 2表示send方法调用完毕
// 3表示服务端返回了部分结果 4表示服务端返回了所有结果
xhr.onreadystatechange = function(){
//判断 (服务端返回了所有结果)
if(xhr.readyState === 4 ){
//判断响应状态码 200 404 403 401 500
//2开头就表示成功
if(xhr.status>=200 && xhr.status<300){
//处理结果
//行 头 空行 体
console.log(xhr.status);//状态码
console.log(xhr.statusText);//响应字符串
console.log(xhr.getAllResponseHeaders());//所有响应
console.log(xhr.response);//响应体
}else{
}
}
}
}
改错心得:注意单词拼写,域名前一定要有http://,要在express语句执行的时候发送请求才会成功响应
如何设置GET请求参数
设置url参数,接上文
xhr.open("GET","http://127.0.0.1:8000/server?a=100&b=200&c=300");
发送POST请求
POST请求有请求头
//1.引入express
const express = require("express");
//2.创建应用对象
const app = express();
//3.创建路由规则
//request 是对请求报文的封装
//response 是对响应报文的封装
app.post('/server',(request,response)=>{
//设置响应头
response.setHeader("Access-Control-Allow-Origin",'*');
//设置响应体
response.send("hello,Ajax POST");
});
//4.监听端口启动服务
app.listen(8000,()=>{
console.log("服务已启动,8000端口监听中....");
})
let box = document.getElementById("result");
box.addEventListener("mouSEO((Search Engine Optimization))ver", ()=>{
const xhr = new XMLHttpRequest();
xhr.open("POST","http://127.0.0.1:8000/server");
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 )
{
if(xhr.status>=200 && xhr.status<300){
box.innerHTML = xhr.response;
}
}
}
})
设置POST请求参数
接上
xhr.send("a:100&b:300");
或者
xhr.send("a=100&b=200");
设置请求头信息
接上
let box = document.getElementById("result");
box.addEventListener("mouSEO((Search Engine Optimization))ver", ()=>{
const xhr = new XMLHttpRequest();
xhr.open("POST","http://127.0.0.1:8000/server");
//设置请求头
xhr.setRequestHeader("自定义","自定义");
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 )
{
if(xhr.status>=200 && xhr.status<300){
box.innerHTML = xhr.response;
}
}
}
})
要加入自定义的头浏览器会报错,要改变一下服务端
//1.引入express
const express = require("express");
//2.创建应用对象
const app = express();
//3.创建路由规则
//request 是对请求报文的封装
//response 是对响应报文的封装
//all表示允许接收各种类型的请求
app.all('/server',(request,response)=>{
//设置响应头
response.setHeader("Access-Control-Allow-Origin",'*');
response.setHeader("Access-Control-Allow-Headers",'*');
//设置响应体
response.send("hello,Ajax POST");
});
//4.监听端口启动服务
app.listen(8000,()=>{
console.log("服务已启动,8000端口监听中....");
})
服务端响应JSON数据
JSON格式
{
"key":"value"
}
服务端传回的响应数据只能是字符串,因此要先把JSON格式的数据转化成字符串,等网页拿到响应数据之后再改为原来的格式
手动转化
服务端:
//1.引入express
const express = require("express");
//2.创建应用对象
const app = express();
//3.创建路由规则
//request 是对请求报文的封装
//response 是对响应报文的封装
app.all("/server",(request,response) => {
response.setHeader("Access-Control-Allow-Origin",'*');
response.setHeader("Access-Control-Allow-Headers",'*');
const data = { name : "atguigu"};
let str = JSON.stringify(data);
response.send(str);
})
//4.监听端口启动服务
app.listen(8000,()=>{
console.log("服务已启动,8000端口监听中....");
})
let result = document.getElementById("result");
result.onclick = function(){
const xhr = new XMLHttpRequest();
xhr.open("POST","http://127.0.0.1:8000/server");
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState===4){
if(xhr.status>=200 && xhr.status<300){
//手动将字符串转为JSON格式
let re = JSON.parse(xhr.response);
result.innerHTML = re.name;
}
}
}
}
自动转化响应体类型 发送请求的类型是POST或是GET都不影响
let result = document.getElementById("result");
result.onclick = function(){
const xhr = new XMLHttpRequest();
//设置响应体数据类型
xhr.responseType = 'json';
xhr.open("GET","http://127.0.0.1:8000/server");
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState===4){
if(xhr.status>=200 && xhr.status<300){
let res = xhr.response;
console.log(typeof res);
console.log(res);
}
}
}
}
安装nodemon
IE缓存问题
let result = document.getElementById("result");
result.onclick = function(){
const xhr = new XMLHttpRequest();
//增加时间参数让IE浏览器实时检测,运用了时间戳
xhr.open("GET","http://127.0.0.1:8000/server?t=" Date.now());
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState===4){
if(xhr.status>=200 && xhr.status<300){
console.log(xhr.response);
}
}
}
}
请求超时与网络异常处理
let btn = document.getElementsByTagName("button")[0];
let page = document.getElementById("result");
btn.addEventListener("click",function(){
const xhr = new XMLHttpRequest();
//超时设置,2s之内不响应则请求取消
xhr.timeout = 2000;
//超时回调
xhr.ontimeout = function(){
alert("网络超时!");
}
//网络异常
xhr.onerror = function(){
alert("网络异常!")
}
xhr.open("GET","http://127.0.0.1:8000/delay");
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState===4){
if(xhr.status>=200 && xhr.status<300){
page.innerText = xhr.response;
}
}
}
})
AJAX取消请求
前提:在网页上设置两个按钮
要在返回相应之前取消请求才能成功!
首先设置服务端,设置为延时响应
const express = require("express");
const app = express();
app.get("/sends", (request, response) => {
response.setHeader("Access-Control-Allow-Origin", "*");
setTimeout(()=>{
response.send("success!");
},3000);//设置延时就是为了及时在响应完成之前取消请求
})
app.listen(8000,()=>{
console.log("8000终端监控中");
})
在script标签中(我用的外联js)
let Send = document.getElementsByTagName("button")[0];
let Cancel = document.getElementsByTagName("button")[1];
let page = document.getElementById("result");
//在外部声明x,这样在才能在两个函数中对x 进行操作
//不能用const进行声明,不然在后面就不能该变值了
let x = null;
Send.addEventListener("click", () => {
x = new XMLHttpRequest();
x.open("GET", "http://127.0.0.1:8000/sends");
x.send();
x.onreadystatechange = function() {
if (x.readyState === 4) {
if (x.status >= 200 && x.status < 300) {
page.innerText = x.response;
}
}
}
Cancel.onclick = function(){
//bort取消发送
x.abort();
}
})
请求重复发送问题
新发送请求的时候自动将前一次发送的请求取消,有利于对服务器减负
想要检验这个功能,要把服务端改为延时响应
const express = require("express");
const app = express();
app.get("/server", (request, response) => {
response.setHeader("Access-Control-Allow-Origin", "*");
setTimeout(()=>{
response.send("success!");
},3000);
})
app.listen(8000,()=>{
console.log("8000终端监控中");
})
Javascript
let btn = document.getElementsByTagName("button")[0];
//提前声明xhr
let xhr = null;
//声明isSending作为标识变量用于判断服务器是否在发送请求。
let isSending = false;
btn.onclick = function(){
//触发事件后先判断是否在发送请求,如果在,那就取消正在发送的请求
if(isSending){
xhr.abort();
}
//重新发送请求
xhr = new XMLHttpRequest();
isSending = true;
xhr.open("GET","http://127.0.0.1:8000/server");
xhr.send();
xhr.onreadystatechange = function() {
if(xhr.readyState == 4){
//判断readyState属性,如果请求发送完毕,即使是失败的也算发送完毕,
//那么这个时候服务器就处于没发送请求的状态的,标识量改为false
isSending = false;
}
}
}
JQuery发送AJAX请求
功能实现的准备:在网页上放置两个按钮一个是POST请求,一个是GET请求
在网页中引入Jquery资源,放在script标签里
如
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.js"></script>
服务端设置:
const express = require("express");
const app = express();
app.get("/server", (request, response) => {
response.setHeader("Access-Control-Allow-Origin", "*");
//设置一个JSON对象时,要注意返回响应体的时候将转为string
let data = {name:"Robin"};
response.send(JSON.stringify(data));
});
app.post("/server",(request,response)=>{
response.setHeader("Access-Control-Allow-Origin","*");
let data = {name:"john"}
response.send(JSON.stringify(data));
});
//通用方法,不一定要是all,也可以是get,post.
//但是如果要传递头信息,就得用all
app.all("/ajax",(request,response)=>{
response.setHeader("Access-Control-Allow-Origin","*");
response.setHeader("Access-control-Allow-Headers","*");//加上这一条才能成功传送Headers头信息
let data = {name:"Frank"};
response.send(JSON.stringify(data));
})
app.listen(8000,()=>{
console.log("8000终端监控中");
})
js文件里:
//以下请求为Jquery语法
$("button").eq(0).click( ()=>{
$.get("http://127.0.0.1:8000/server",{a:100,b:500},(data)=>{
console.log(data);
});
});
$("button").eq(1).click( ()=>{
$.post("http://127.0.0.1:8000/server",{c:30},(data)=>{
console.log(data);
},'json');//后设参数json,这样编译器会将响应体自动转化为json对象
});
$("button").eq(2).click(function(){
$.ajax({
//请求地址
url:'http://127.0.0.1:8000/ajax',
//参数
data:{a:200,b:150},
//请求类型
type:'GET',
//响应体结果
dataType:'json',
//成功的回调
success:function(data){
console.log(data);
},
//超时时间
timeout:2000,
//失败的回调
error:function(){
console.log("获取失败!");
},
//头信息
Headers:{age:18}
}
)
})
Axios发送请求
在服务端必须用all来接收请求,才能成功
写法一
let btns = document.querySelectorAll("button");
//用get方法
btns[0].addEventListener("click",()=>{
axios.get("http:137.0.0.1:8000/axios",{
params: {
a:100,
b:300
},
headers: {
name:"atguigu",
id:123123
},
}).then(value => {
console.log(value);
})
})
写法二
//用post方法
btns[1].onclick = function() {
axios.post("http://127.0.0.1:8000/axios",
{
//url
params:{
id:200,
ip:7
},
//请求头参数
headers: {
name:"atmon",
id:456456
},
//请求体
data: {
username:"xiaoB",
password:123456
}
}).then(value => {
console.log(value);
})
}
设置baseURL axios.defaults.baseURL = "http://127.0.0.1:8000";
let btns = document.querySelectorAll("button");
//配置baseURL
axios.defaults.baseURL = "http://127.0.0.1:8000";
//用get方法
btns[0].addEventListener("click",()=>{
//axios.get({url},{请求体},{其他配置})
axios.get("/axios",{
params: {
a:100,
b:300
},
headers: {
name:"atguigu",
id:123123
},
}).then(value => {
console.log(value);
})
})
btns[1].onclick = function() {
axios.post("/axios",
{
username:"xiaoB",
password:123456
},
{
//url参数
params:{
id:200,
ip:7
},
//请求头参数
headers: {
name:"atmon",
id:456456
}
}).then(value => {
console.log(value);
})
}
写法三 要用all才能接收到请求
btns[2].onclick = function() {
axios({
//请求方法
method: 'POST',
//url
url:"/axios",
//url参数
params:{
id:159,
ip:100
},
//头信息
headers: {
a:320,
b:410
},
//请求体
data: {
username:"admin2",
password:2589
}
} ).then(response => {
console.log(response);
})
使用fetch函数发送AJAX请求
准备一个按钮
服务端
const express = require("express");
const app = express();
app.all("/fetch-server",(request,response) => {
response.setHeader("Access-Control-Allow-Origin","*");
response.setHeader("Access-Control-Allow-Headers","*");
let data = {name:"Ellen"};
response.send(JSON.stringify(data));
})
app.listen(8000,()=>{
console.log("8000端口监听中");
})
JS文件
let btn = document.getElementsByTagName("button");
btn[0].onclick = function(){
fetch("http://127.0.0.1:8000/fetch-server?a=100&b=250",
{
//请求方法
method:"POST",
//请求头
headers:{
name:"atGPT"
},
//请求体
body : "username=admin&password=15234"
}).then(response=>{
//返回响应体,表明响应体是字符串类型
return response.text;
//如果写成 return response.json
//那么服务器会自动将其转化为json数据类型
}).then(response=>{
console.log(response);
});
}
同源策略
同源:协议、域名、端口号必须完全相同。
违背同源策略就是跨域
如何解决跨域
JSONP
-
JSONP是什么
JSON with Padding ,是一个非官方的跨域解决方案
-
怎么工作的?
在网页有一些标签天生具有跨域能力,比如:img,link,inframe,script
JSONP就是利用script标签的跨域能力发送请求的
-
JSONP的使用
向相同服务端口发送请求
<script scr = "(http协议版的js地址)"></script>
向其它服务端口发送请求
(一个自定义的8000端口)
<script src="http://127.0.0.1:8000/jsonp-server"></script>
端口代码
const express = require("express");
const app = express();
app.get("/jsonp-server",(request,response)=>{
response.setHeader("Access-Control-Allow-Origin","*");
response.setHeader("Access-Control-Allow-Headers","*");
response.send("hello jsonp");
})
app.listen("8000",()=>{
console.log("8000端口启动");
})
response返回的内容是"hello jsonp"
这样的内容能作为响应体返回到发送端,但不能被解析
> Uncaught SyntaxError: Unexpected identifier 'jsonp' (at jsonp-server:1:7)
应当返回标准js文档
比如:
response.send('console.log("hello jsonp")');
这样控制台可以打印出 hello jsonp
还可以返回函数调用
response.end(`handle(a)`);//handle() 和 a 分别是在全局中定义好了的函数体和数据
原生JSONP实现
//1.创建script标签
const script = document.createElement("script");
//2.设置标签的src属性
script.src = "http://127.0.0.1:8000/jsonp-server";
//3.将script插入到文档中
document.body.appendChild(script);
js
let btn = document.getElementsByTagName("button");
let input = document.getElementsByTagName("input")[0];
let result = document.getElementById("result");
function handle(data){
result.innerText = data.name;
}
input.onblur = function() {
let username = this.value;
const script = document.createElement("script");
script.src="http://127.0.0.1:8000/jsonp-server";
document.body.appendChild(script);
}
服务端口
const express = require("express");
const app = express();
app.get("/jsonp-server",(request,response)=>{
response.setHeader("Access-Control-Allow-Origin","*");
response.setHeader("Access-Control-Allow-Headers","*");
const data = {
name:"用户名已存在"
};
response.send(`handle(${JSON.stringify(data)})`);//这一步重点理解
//服务端只能返回字符串,但不能知识data,JSON内置函数将JSON类型转化为字符串!返回后才能被解析到
})
app.listen("8000",()=>{
console.log("8000端口启动");
})
####用Jquery发送JSONP请求
js语句
$(`button`).eq(0).click(function(){//注意callback,这是固定格式
$.getJSON(`http://127.0.0.1:8000/jquery-jsonp?callback=?`,function(data){
//设置回调函数处理响应体
$("#result").html(`
姓名:${data.name}<br>
年龄:${data.age}<br>
`)
})
})
服务端语句
const express = require("express");
const app = express();
app.all("/jquery-jsonp",(request,response)=>{
const data = {
name:"Ellen",
age:19,
hometown:"A"
};
//接收callback参数
let cb = request.query.callback;
//将数据转化为字符串
let str = JSON.stringify(data)
//返回结果
response.end(`${cb}(${str})`);
})
app.listen("8000",()=>{
console.log("8000端口启动");
})
CORS实现跨域
CORS通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应之后就会对该响应放行
Access-Control-Allow-Origin
Access-Control-Expose-Headers
Access-Control-Max-Age 做域请求结果缓存
Access-Control-Allow-Headers 头信息
等等等
后面的值用"*"表示所有方法或所有端口通用
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgbbage
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01