【前端】Ajax请求以及配合express后台服务的用法

一、网络协议

HTTP全称为HyperText Transfer Protocol,超文本传输协议,是在web上进行数据交换的基础,是一种“客户端-服务器端”协议,设计的最初是为了提供一种发布和接收HTML页面的方法。

HTTP请求与响应消息

客户端和服务端通过交换各自的消息进行交互,像浏览器发出的消息叫做请求(requests),被服务端回应的消息叫做响应(responses)。HTTP消息采用ASCII编码的多行文本构成,请求消息和响应消息具有相似的结构。

Context-type简介

Content-type是网络上传输内容的格式标准,用于定义网络文件的类型和网页的编码。

Content-type常见格式

用multipart/form-data标准传输的格式,传输数据文件为主:

  • text/html:HTML格式
  • text/plain:纯文本格式
  • text/xml:XML格式
  • image/jpeg:jpg图片格式
  • image/png:png图片格式
  • image/gif:gif图片格式

用application标准传输的格式,传输数据流、字符串为主:

  • application/xhtml+xml:XHTML格式
  • application/xml:XML数据格式
  • application/atom+xml:Atom XML聚合格式
  • application/json:JSON数据格式
  • application/pdf:pdf格式
  • application/msword:Word文档格式
  • application/octet-stream:二进制流数据
JSON

JSON是JavaScript Object Notation的缩写,是一种轻量级的数据交换格式,多数用于交换字符串类型的数据。
JSON的序列化和反序列化,序列化最大的优势是跨平台的存储和数据传输,因此JSON是多数据兼容的。把在浏览器中填写的数据,通过请求通过JSON格式,发送到服务器,服务器把多条数据合并后,再用JSON格式返回浏览器响应。

FormData

FormData是HTML5新加进来的一个类,主要用于向服务器上传数据,可以模拟表单数据。相比JSON,FormData不但支持字符串传输,同时支持文件的二进制传输,因此在上传视频、图片、音频上比较有优势。

//FormData传输数据
let formData = new FormData(form);
formData.set('username','name')

// FormData传输文件
const file = document.querySelector("file_name").files[0];
let formData = new FormData();
formData.append("photo",file);

//FormData请求格式
$.ajax({
	url:"",//上传地址
	type:"POST",
	data:formData,//传入实例化的formData对象,包含了要上传的文件
	contentType:false,//在请求服务器的时候,数据有非字符串格式的内容(文件是二进制)
	processData:false//formData对象不需要转换成参数字符串
})
常用服务器反馈状态码
状态码英文中文
200OK客户端请求成功
201Created表示请求已经被成功处理
302redirect临时重定向
400Bad Request由于语法无效
403Forbidden拒绝授权访问
500Internal Server Error服务器发生不可预期的错误
HTTP缓存概念

缓存是一种保存资源副本并在下次请求时直接使用该副本。当Web缓存发现请求的资源已经被存储,便拦截请求,返回该资源的拷贝,而不会去原服务器重新下载。
优点:

  • 缓解服务器内存消耗,减少程序执行压力,提升服务器的整体性能
  • 提升服务器资源的加载速度,减少某些资源占用系统资源的时间
  • 降低带宽损耗,减少网络阻塞的出现
  • 提升了网站的响应速度

缓存类型:共享缓存、
强制缓存:根据Expires(请求头里的过期时间)判断,浏览器再次加载资源时,如果在这个过期时间内,则命中强缓存,并不会向服务端发起请求,展示为200状态、
协商缓存:客户端向服务端发送带有If-None-Match和If-Modified-Since的请求进行协商判断,如果资源没有变化继续使用本地缓存,记录为304状态;如果资源发生变化,服务端响应数据,记录为200状态。

缓存控制:Cache-Control头用来区分对缓存机制的支持情况,请求头和响应头都支持这个属性。

  • 禁止进行缓存
    Cache-Control:no-store
    Cache-Control:no-cache,no-store,must-revalidate
  • 强制确认缓存
    Cache-Control:no-cache
    Pragma:no-cache
  • 缓存过期机制
    Cache-Control:max-age=31536000
    Expires:Wed,21 Oct 2015 08:00:00 GMT(0即代表过去的日期已经过期,如果在Cache-Control中设置了max-age或s-max-age指令,那么会忽略Expires)
  • 缓存验证确认
    Cache-Control:must-revalidate
XML

XML指可扩展标记语言(EXtensible Markup Language),XML和HTML类似,HTML 指的是超文本标记语言:(HyperText Markup Language),也是标记语言
不同的是HTML中都是预定义标签,用来展示数据信息,而XML全都是自定义标签,用来传输和存储数据。
最开始AJAX使用的是XML,服务器返回的是XML格式的字符串,JS进行数据提取以及数据展示,后来XML被JSON取代,JSON更加简洁、灵活。

二、Cookie

Cookie存储于当前电脑上的文本文件中,用于在本地存储Web页面的信息的对象。

创建Cookie
function setCookie(cname,cvalue,exdays){
	var d = new Date();
	d.setTime(d.getTime()+(exdays*24*60*60*1000));
	var expires="expires="+d.toGMTString();
	document.cookie = cname+"="+cvalue+";"+expires;
}
获取Cookie
function getCookie(cname){
	var name = cname+"=";
	var ca = document.cookie.split(";");
	for(var i=0;i<ca.length;i++){
		var c= ca[i].trim();
		if(c.indexOf(name)==0) return c.substring(name.length,c.length)
	}
	return "";
}
SessionStorage

用于临时保存同一窗口或标签页的数据。

  • 存储在SessionStorage里面的数据在页面会话结束时会被清除
  • 页面会话在浏览器打开期间一直保持,并且重新加载或恢复页面仍会保持原来的页面会话
  • 打开多个相同的URL的Tabs页面,会创建各自的SessionStorage
  • 关闭对应浏览器标签或窗口,会清除对应的SessionStorage
//保存数据到sessionStorage
sessionStorage.setItem("key","value");
//从sessionStorage获取数据
sessionStorage.getItem("key");
//删除保存的数据
sessionStorage.removeItem("key");
//从sessionStorage删除保存的所有数据
sessionStorage.clear();
LocalStorage

存储在LocalStorage的数据可以长期保留,LocalStorage中的键值对总是以字符串的形式存储。

localStorage.setItem("key","value");
localStorage.getItem("key");
localStorage.removeItem("key");
localStorage.clear()
区别

生命周期:

  • Cookie的生命周期可以通过设置过期时间来控制,过期后会被自动删除。
  • SessionStorage中存储的数据只在当前会话期间有效,当浏览器关闭时会被清除。
  • LocalStorage中存储的数据会持久保存在客户端,即使浏览器关闭也不会丢失。即使超出了浏览器规定的大小,也不会清空数据,只会报错。

存储容量:Cookie的大小有限制,通常不能超过4KB。sessionStorage和localStorage的存储容量要大得多,一般可以达到5MB或更多。
作用域:

  • Cookie和localStorage在相同的协议、主机名、端口下是共享的,可以在不同页面之间共享数据。
  • sessionStorage的作用域是以窗口或标签页为单位的,它们只能在同一个窗口或标签页中共享数据。

数据传输:Cookie会随着每次HTTP请求一起发送到服务器端,这会增加额外的网络流量。而sessionStorage和localStorage中存储的数据只存在于客户端,不会被发送到服务器端。

三、ajax介绍

AJAX全称Asynchronous JavaScript And XML,就是异步的JS和XML。通过它可以在浏览器中向服务器发送异步请求,无刷新获取数据。它不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。实现AJAX的执行步骤如4.2。

1. 优点:
1.1 无需刷新页面与服务器端通信
1.2 允许根据用户事件更新部分页面内容
2. 缺点:
2.1 没有浏览历史,不能回退
2.2 存在跨域问题
2.3 SEO(搜索引擎优化)不友好,即页面上的数据是Ajax请求成功后的返回数据,在网页HTML里不存在这个信息,所以爬虫爬取不到想要的数据

四、 express 框架

Express是基于Node.js平台,快速、开放、极简的Web开发框架。可以借助这个框架,来进行一些简单的Ajax操作。

4.1 设置服务端

npm install express

基本使用:

//server.js
//1.引入express
const express = require('express');
//2.创建应用对象
const app = express();
//3.创建路由规则,request和response分别是请求报文和响应报文的封装
app.get('/',(request,response)=>{
	//设置响应头,允许跨域
	response.setHeader('Access-Control-Allow-Origin','*')
	//响应结果
	response.send('成功启动服务')
})
//4.监听端口启动服务
app.listen(8000,()=>{
	console.log('服务启动,正在监听端口')
})

在当前目录下,启动终端,输入node 文件名,即可启动http服务。在浏览器中输入127.0.0.1:8000可以访问。终止服务,在终端窗口Ctrl+C。

如果想要配置路径下访问的页面,可以这样:

//server.js
app.get('/home',(request,response)=>{
	response.sendFile(_dirname + '/index.html');
	//home路径下会访问相对路径下的index.html文件,作为响应页面
})

4.2 设置前台请求
get请求:

//创建XMLHttpRequest对象
const xhr =  new XMLHttpRequest();
//初始化请求方式和url,与服务器建立连接
//get请求可以直接在url后面拼接参数,例:'http://127.0.0.1:8000?a=2'
xhr.open('GET','http://127.0.0.1:8000');
//xhr.open(method,url,async) async默认为true,表示是否异步
//发送请求
xhr.send();
//处理服务端返回结果的方法
//readystate 0(初始化) 1(open 调用完毕) 2(send调用完毕) 3(服务端返回部分结果) 4(服务端返回所有结果)
xhr.onreadystatechange = function(){
	if(xhr.readyState == 4){
		if(xhr.status >= 200 && xhr.status < 300){
			console.log(xhr.status);//状态码
			console.log(xhr.statusText);//状态文本
			console.log(xhr.getAllResponseHeaders());//所有响应头
			console.log(xhr.response);//响应体
			console.log(xhr.responseText)//将服务器端响应作为文本字符串返回
			console.log(xhr.responseXML)//将响应作为一个XMLDocument对象返回,该对象可以使用JavaScript DOM进行解析。
		}
	}
}

post请求:

const xhr =  new XMLHttpRequest();
//设置响应体的数据类型,这样在响应时不需要手动转化json字符串
xhr.responseType= 'json'
xhr.open('POST','http://127.0.0.1:8000/server');
//设置请求头
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
xhr.send('a=100&c=200');
xhr.onreadystatechange = function(){
	if(xhr.readyState == 4){
		if(xhr.status >= 200 && xhr.status < 300){
			console.log(xhr.response);//响应体
			//如果xhr.response返回的是JSON字符串,则
			console.log(JSON.parse(xhr.response))
		}
	}
}

同时,服务端,增加处理post请求的代码:

//server.js
const express = require('express');
const app = express();
//get为get请求、post为post请求,all为所有类型的请求,如果设置完允许所有类型请求头,还不能请求成功就改为all请求
app.get('/server',(request,response)=>{
	response.setHeader('Access-Control-Allow-Origin','*')
	//如果前台传递自定义的headers,需要设置允许所有请求头
	response.setHeader('Access-Control-Allow-Headers','*')
	const data = {
		name: 'Nick' 
	}
	//如果想要返回json字符串,则用JSON.stringfy(data),当作send方法的参数
	response.send(JSON.stringfy(data));
})
//4.监听端口启动服务
app.listen(8000,()=>{
	console.log('服务启动,正在监听端口')
})

4.3 自动启动包

如果频繁进行修改server.js,可以安装nodemon这个包,如果有代码更改,可以自动重启服务端服务。

npm install -g nodemon

安装成功之后,直接nodemon server.js启动服务。

4.4 ajaxIE浏览器缓存问题

由于,IE浏览器会缓存ajax请求,响应结果不能实时更新,所以可以更改请求url,形成重新请求,来更新请求结果。

var xhr =  new XMLHttpRequest();
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);//响应体
		}
	}
}

另一种方法区分不同浏览器中的AJAX:

var httpRequest;
if(window.XMLHttpRequest){
	httpRequest = new XMLHttpRequest();
	//适用于Chrome,Firefox,Safari
}else if(window.ActiveXObject){
	try {
		httpRequest = new ActiveXObject("Msxml2.XMLHTTP")
		//IE7+
	}catch(e){
	}
}
return httpRequest;

4.5 ajax超时以及网络异常提醒

var xhr =  new XMLHttpRequest();
xhr.timeout = 2000;
//如果两秒内没有响应,就取消请求
xhr.ontimeout = function(){
	alert('请求异常,请稍后重试')
}
//超时回调
xhr.onerror = function(){
	alert('您的网络似乎出了一些问题!')
}
//网络异常回调
xhr.open('GET','http://127.0.0.1:8000');
xhr.send();
xhr.onreadystatechange = function(){
	if(xhr.readyState == 4){
		if(xhr.status >= 200 && xhr.status < 300){
			console.log(xhr.response);//响应体
		}
	}
}

服务端代码变动:

//server.js
const express = require('express');
const app = express();
app.get('/',(request,response)=>{
	response.setHeader('Access-Control-Allow-Origin','*')
	setTimeout(()=>{
		response.send('延时响应')
	},3000)
})
app.listen(8000,()=>{
	console.log('服务启动,正在监听端口')
})

4.6 ajax取消请求以及避免重复请求

var xhr =  new XMLHttpRequest();
xhr.open('GET','http://127.0.0.1:8000');
xhr.send();
xhr.abort();
//必须用同一个对象取消请求

如果出现服务器响应慢,用户一直没收到数据,因此一直发送重复请求的情况。这时,就可以通过新建一个标识来判断是否处在发送请求中:

var xhr = null;
if(sendflag) xhr.abort();
//如果正在发送,那么取消正在发送的请求,减轻服务器压力,重新请求
xhr =  new XMLHttpRequest();
let sendflag = false;
sendflag = true;
xhr.open('GET','http://127.0.0.1:8000');
xhr.send();
xhr.onreadystatechange = function(){
	if(xhr.readyState == 4){
		if(xhr.status >= 200 && xhr.status < 300){
			console.log(xhr.response);//响应体
			sendflag = false;
			//请求成功后修改标识
		}
	}
}

五、jQuery框架的Ajax请求

服务端代码:

//server.js
const express = require('express');
const app = express();
app.all('/',(request,response)=>{
	response.setHeader('Access-Control-Allow-Origin','*')
	//如果前台传递自定义的headers,需要设置允许所有请求头
	response.setHeader('Access-Control-Allow-Headers','*')
	var list = {result:'success'}
	response.send(JSON.stringfy(list))
})
app.listen(8000,()=>{
	console.log('服务启动,正在监听端口')
})

5.1 get

get方法的三个参数分别是请求地址,参数以及回调方法:

$.get('http://127.0.0.1:8000',{a:1,b:2},function(data){
	console.log(data)
	//data为响应结果
},'json')
//响应体自动转为json格式

5.2 post

post请求只需要,方法改为post方法,参数不变:

$.post('http://127.0.0.1:8000',{a:1,b:2},function(data){
	console.log(data)
	//data为响应结果
},'json')

5.3 通用请求

$.ajax({
	url:'http://127.0.0.1:8000',
	data:{a:1,b:2},
	headers:{
		c:2,
		a:1
	},
	//自定义头
	type:'GET',
	dataType:'json',
	//响应体结果数据类型
	success:function(data){
		console.log(data)
		//data为响应结果
	},
	timeout:2000,
	//超时时间
	error:function(){
		console.log('出错了!')
	}
	//失败回调
})

六、Axios的Ajax请求

6.1 安装axios包

npm install axios

以及在单页面里面直接引用:

//Using jsDelivr CDN:
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"><script>
//Using unpkg CDN:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

h5中,一些html元素提供了对CORS的支持,有一个跨域属性,它允许配置元素获取数据的CORS请求。如果说引用脚本出错,可以加上crossorigin="anonymous",对script元素的请求不设置凭据标志。

6.2 get请求

//配置默认url
axios.defaults.baseURL = 'http://127.0.0.1:8000'
axios.get('/',{
	params:{
		a:2
	},//请求参数
	headers:{
		age:20
	}//请求头
})
//基于promise的处理数据
.then(value=>{
	console.log(value);
})
//.then(function(response){
//	console.log(response);
//})
.catch(function(error){
	console.log(error)
})
.then(function(){
	//always executed
})

6.3 post请求

//配置默认url
axios.defaults.baseURL = 'http://127.0.0.1:8000'
axios.post('/',{name:'you'}//请求体,{
		headers:{
			age:20
		}//请求头
})
.then(function (response) {
    console.log(response);
})
.catch(function (error) {
    console.log(error);
});

6.4 ajax请求

// 发起一个post请求
axios({
  method: 'post',
  url: '/',
  params: {
   	a:2
  },
  headers:{
	age:20
   },//请求头
   data:{
	token:"admin"
	}//请求体
}).then(response=>{
	console.log(response)
})

请求体与请求参数的区别,也就是params与data的区别:
get请求,请求参数在请求行中也就是url后面,同时也没有请求体,不太安全;
post请求,请求参数在请求体中,相对安全。

七、 Fetch()函数

fetch()方法用于发起获取资源的请求,它返回一个promise,这个promise会在请求响应后被resolve,并传回Response对象。

fetch('http://127.0.0.1:8000',{
	method:'POST',
	headers:{
		name:'admin'
	},
	body:'name=admin'
}).then(response=>{
	console.log(response)
	return response.text();
	//return response.json();转换成json格式
}).then(response=>{
	console.log(response)
})

八、 跨域问题

ajax默认遵循同源策略,最早由netscape公司提出,是浏览器的一种安全策略。
同源:协议、域名、端口号必须完全相同。跨域即,违背同源策略。
出于安全原因,浏览器限制从脚本内发起的跨域HTTP请求。例如,XMLHttpRequest和Fetch API遵循同源策略。这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源。
常见的跨域分为以下两种:

  • 完全跨域:一个顶级域名方向另一个顶级域名。
  • 跨子域:相同顶级域名下的两个子级域名相互通信。

8.1 如何解决跨域
jsonp是一个非官方的跨域解决方案,支持get请求,不支持post请求。html中有一些标签,是可以跨域的,比如说script标签,用script标签来发送请求:

<script src="http://127.0.0.1:8000/jsonp"></script>

方法返回响应也是可以在控制台正常输出hello jsonp,当然返回的数据要是script标签能够解析的脚本

//server.js
const express = require('express');
const app = express();
app.all('/jsonp',(request,response)=>{
	response.send('console.log("hello jsonp")')
})
app.listen(8000,()=>{
	console.log('服务启动,正在监听端口')
})

jsonp怎么用:

var body = document.querySelector('body');
function changeBody(data){
	body.style.border='1px solid #f00'
	body.innerText = data
}
var script = document.createElement('script');
script.src = 'http://127.0.0.1:8000/jsonp';
document.body.appendChild(script);

服务端代码:

//server.js
const express = require('express');
const app = express();
app.all('/jsonp',(request,response)=>{
	var data = {
		result:'jsonp请求成功'
	}
	var str = JSON.stringfy(data);
	response.send(`changeBody(${str})`);
})
app.listen(8000,()=>{
	console.log('服务启动,正在监听端口')
})

8.2 jQuery发送jsonp请求

$.getJSON('http://127.0.0.1:8000/jsonp?callback=?',function(data){
	console.log(data);
})

服务端代码:

//server.js
const express = require('express');
const app = express();
app.all('/jsonp',(request,response)=>{
	var data = {
		result:'jsonp请求成功'
	}
	let cb = request.query.callback;
	//接收callback参数,接收到的参数是jQuery字符串
	var str = JSON.stringfy(data);
	response.send(`&{cb}(${str})`);
})
app.listen(8000,()=>{
	console.log('服务启动,正在监听端口')
})

8.3 CORS

CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS 是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持get 和 post 请求。跨域资源共享标准新增了一组 HTTP 头部字段,通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行。
可用于发起跨域请求的头部字段,通常以access-control开头,下面是一些常用的:

//server.js
app.get('/',(request,response)=>{
	response.setHeader('Access-Control-Allow-Origin','*')
	response.setHeader('Access-Control-Allow-Headers','*')
	response.setHeader('Access-Control-Allow-Method','*')
	response.send('CROS');
})

跨域资源共享机制的工作原理主要应用于三个场景:

  • 简单请求
    • 使用下列请求方法之一:GET、HEAD或POST
    • 不得人为设置下列集合之外的其他首部字段:Accept、Accept-Language、Content-Language、Content-Type
    • Content-Type的值仅限于下列三者之一:text/plain、multipart/form-data、application/x-www-form-urlencoded
  • 预检请求(在浏览器与服务器正式请求之前,浏览器会发送OPTION请求进行预检,以获知服务器是否允许该实际请求,所以这一次的option请求称为预检请求。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据。)
    • 使用下列请求方法之一:PUT、DELETE、CONNECT、OPTIONS、TRACE或PATH
    • 请求头中包含自定义头部字段
    • 向服务器发送了application/json格式的数据
  • 认证请求
    • 对于跨域的XMLHttpRequest请求,浏览器不会发送身份凭证信息,如果要发送,需要设置xmlHttpRequest.withCredentials = true;,使得向服务器发送Cookies,服务器返回响应首部字段ACCESS-Control-Allow-Credentials:true
    • 如果服务器端的响应中携带ACCESS-Control-Allow-Credentials:true,浏览器将不会把响应内容返回给请求的发送者。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值