• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

前后端交互,http,ajax

武飞扬头像
写代码的小玉
帮助1

前后端数据交互

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的使用

请求报文

  1. 行 GET /POST 路径:url

  2. Host: atguigu.com
    Cookie: name=guigu
    Content-type: application/x-www-form-urlencoded
    User-Agent: chrome 83
    
    

  3. 空行

  4. 体(对于GET请求,请求体为空;对于POST请求,请求体不为空)

    username=admin&password=admin

响应报文

  1. 行 协议版本 响应状态码 响应字符串

  2. 头 Content-Type: text/html; charset=utf-8

    Content-length: 2048

    Content-encoding: gzip

  3. 空行

  4. <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端口监听中....");
})

gitee.com/river-ice/n…

发送请求

发送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

  1. JSONP是什么

    JSON with Padding ,是一个非官方的跨域解决方案

  2. 怎么工作的?

    在网页有一些标签天生具有跨域能力,比如:img,link,inframe,script

    JSONP就是利用script标签的跨域能力发送请求的

  3. 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
系列文章
更多 icon
同类精品
更多 icon
继续加载