前端工程化17-邂逅原生的ajax、跨域、JSONP

5、邂逅原生的ajax

5.1、什么是ajax

AJAX 全称为Asynchronous Javascript And XML,就是异步的 JS 和 XML。通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势:页面无刷新获取数据。AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。

5.2、XML简介

XML 可扩展标记语言。

XML 被设计用来传输和存储数据。

XML和HTML类似,不同的是HTML中都是预定义标签,而XML中没有预定义标签,全都是自定义标签,用来表示一些数据。

用XML表示一个学生数据:

<student>
        <name>孙悟空</name>
        <age>18</age>
        <gender></gender>
</student>

现在已经被JSON取代了。

{"name":"孙悟空","age":18,"gender":"男"}

但是还有一些老系统在用这种数据交换格式,因为替换的成本实在太大,不能接受

5.3、ajax的优点

可以无需刷新页面而与服务器端进行通信。

允许你根据用户事件来更新部分页面内容。

5.4、AJAX的缺点

没有浏览历史,不能回退;固有问题

存在跨域问题;可以解决

SEO不友好; 没有意义,有竞价排名这个东西

5.5、AJAX核心对象

XMLHttpRequest,AJAX的所有操作都是通过该对象进行的。

函数、函数对象、方法

5.6、搭建测试ajax请求的服务器

创建项目(变成一个符合npm规范的包)

​ npm init

​ yarn inti

规定项目名称(不能有大写字母,也不能有数字开头)

​ ajax_0826

​ 一路回车

安装express

​ yarn add express

新建一个server.js文件

​ 下带附件

启动服务器

​ node server.js

​ 右键 Code Runner插件

​ 推荐敲命令,后期我们脚手架里都是敲命令

热启动node服务

​ nodemon server.js

服务器附件文件

//引入express
const express = require('express')
const cors = require('cors')

//创建app实例对象
const app = express()
//使用中间件解析urlencoded编码形式的请求体参数
app.use(express.urlencoded({extended:true}))
//使用中间件解析json编码形式的请求体参数
app.use(express.json())
app.use(cors())

//暴露静态资源
app.use(express.static(__dirname+'/src'))

//响应GET请求--可以接收query参数
app.get('/test_get',(request,response)=>{
	console.log('有人请求test_get了--携带的query参数是:',request.query);
	/* response.setHeader('Access-Control-Allow-Origin','*')
	response.setHeader('Access-Control-Expose-Headers','*') */
	response.send('hello_test_get')
})

//响应GET请求--可以接收params参数
app.get('/test_get2/:name/:age',(request,response)=>{
	console.log('有人请求test_get2了--携带的params参数是:',request.params);
	response.send('hello_test_get2')
})

//响应get请求
app.get('/get_person',(request,response)=>{
	console.log('有人请求get_person了');
	const person = {name:'tom',age:18,sex:'女'}
	response.send(JSON.stringify(person))
})

//响应get请求
app.get('/get_person_delay',(request,response)=>{
	console.log('有人请求get_person了');
	const person = {name:'tom',age:18,sex:'女'}
	setTimeout(()=>{
		response.send(JSON.stringify(person))
	},3000)
})

//响应POST请求--可以接收请求体参数
app.post('/test_post',(request,response)=>{
	console.log('有人请求test_post了--携带的请求体参数是',request.body);
	response.send('hello_test_post')
})

//响应get请求---jquery
app.get('/test_jquery_get',(request,response)=>{
	console.log('有人请求test_jquery_get了',request.query);
	const car = {name:'马自达·阿特兹',price:'25万'}
	response.send(JSON.stringify(car))
})

//响应post请求----jquery
app.post('/test_jquery_post',(request,response)=>{
	console.log('有人请求test_jquery_post了',request.body);
	const car = {name:'马自达·阿特兹',price:'25万'}
	response.send(JSON.stringify(car))
})

/* app.options('/test_put',(request,response)=>{
	response.setHeader('Access-Control-Allow-Origin','*')
	response.setHeader('Access-Control-Expose-Headers','*')
	response.setHeader('Access-Control-Allow-Methods','*')
	response.send()
}) */

app.put('/test_put',(request,response)=>{
/* 	response.setHeader('Access-Control-Allow-Origin','*')
	response.setHeader('Access-Control-Expose-Headers','*') */
	response.send('hello_test_put')
})

app.get('/test_jsonp',(request,response)=>{
	const {callback} = request.query
	console.log(callback);
	const person = [{name:'tom',age:18},{name:'老刘',age:5}]
	response.send(`${callback}(${JSON.stringify(person)})`)
})

//监听
app.listen(8080,(err)=>{
	if(!err) {
		console.log('测试ajax请求的服务器开启成功了!测试地址如下');
		console.log('http://127.0.0.1:8080/1_ajax小试牛刀.html');
		console.log('http://127.0.0.1:8080/2_xhr的5种状态.html');
		console.log('http://127.0.0.1:8080/3_ajax_get请求.html');
		console.log('http://127.0.0.1:8080/4_ajax_post请求.html');
		console.log('http://127.0.0.1:8080/5_ajax_解析json数据.html');
		console.log('http://127.0.0.1:8080/6_ajax_处理IE浏览器get请求缓存问题.html');
		console.log('http://127.0.0.1:8080/7_ajax请求的异常与超时处理.html');
		console.log('http://127.0.0.1:8080/8_ajax取消请求.html');
		console.log('http://127.0.0.1:8080/9_避免多次重复请求.html');
		console.log('http://127.0.0.1:8080/10_jquery封装的ajax.html');
		console.log('http://127.0.0.1:8080/11_演示回调地狱.html');
	}
})

5.6、如何使用AJAX的核心对象

//1.创建XMLHttpRequest实例对象
const xhr = new XMLHttpRequest()
//2.设置请求信息
xhr.open(method,url) //配置请求
xhr.setRequestHeader(key,value)//设置请求头(可选)
//3.发送请求
xhr.send(body) //get请求不传body参数,只有post请求使用
//4.接收响应
xhr.onreadystatechange = ()=>{
    if(xhr.readyState === 4 && xhr.status === 200 ){
            			console.log(xhr.response)
    }
}

5.7、解决IE缓存问题

问题:在一些浏览器中(IE),由于缓存机制的存在,ajax只会发送的第一次请求,剩余多次请求不会在发送给浏览器而是直接加载缓存中的数据。

解决方式:浏览器的ajax缓存是根据url地址来记录的,所以我们只需要修改url地址即可避免缓存问题

xhr.open('get','url/t='+Date.now())
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>6_ajax_处理IE-get请求缓存问题</title>
		<style>
			#content{
				width: 300px;
				height: 100px;
				border: 1px solid black;
				margin-top: 10px;
			}
		</style>
	</head>
	<body>
		<h3>该页面是测试:ajax_处理IE-get请求缓存问题</h3>
		<button id="btn">点我发送请求(原生js-ajax-get)</button>
		<div id="content"></div>
		<script type="text/javascript" >
			const btn = document.getElementById('btn')
			const content = document.getElementById('content')

			btn.onclick = function(){
				//实例xhr
				const xhr = new XMLHttpRequest()

				//绑定监听
				xhr.onreadystatechange = function(){
					if(xhr.readyState === 4){
						if(xhr.status >= 200 && xhr.status <300){
							console.log(xhr.response);
						}
					}
				}
				
				//配置请求
				xhr.open('GET','http://127.0.0.1:8080/get_person?t='+Date.now())

				//responseType用于指定返回数据的格式
				xhr.responseType = 'json'

				//发送请求
				xhr.send()
			}
		</script>
	</body>
</html>

强缓存、协商缓存

浏览器禁用缓存 Disable cache

按住shift,点刷新,或者shift+f5,强制刷新后,点击获取数据。发现数据http请求状态码为304,证明本次请求走了协商缓存

关闭浏览器,关闭服务器,从新打开浏览器服务器

第一次请求状态码为200,数据成功回来,第二次请求状态码为200,第三次状态码为304,这是因为浏览器发现地址栏信息并没有发送对应的改变,,他会去问下服务器,你的数据是否发生了变化,服务器发现没变,给个304 你小子走协商缓存就好了,协商缓存终归还是给服务器发送了请求

IE这个东西就非常的武断,地址没变直接就会走缓存

5.8、AJAX请求状态

xhr.readyState 可以用来查看请求当前的状态

  • 0: 表示XMLHttpRequest实例已经生成,但open未调用。

  • 1: open已调用,但send还未调用,此时仍然可以修改请求头信息。

  • 2: 表示send()方法已经执行,并且头信息和状态码已经收到。

  • 3: 表示正在接收服务器传来的部分数据。

  • 4:表示数据已经接收完毕

5.9、原生AJAX小试牛刀

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>1_ajax小试牛刀</title>
		<style>
			#content{
				width: 300px;
				height: 100px;
				border: 1px solid black;
				margin-top: 10px;
			}
		</style>
	</head>
	<body>
		<h3>该页面是测试:ajax小试牛刀</h3>
		<button id="btn">点我发送请求(原生js-ajax-get)</button>
		<div id="content"></div>
		<script type="text/javascript" >
			//获取按钮
			const btn = document.getElementById('btn')
			const content = document.getElementById('content')
			//给按钮绑定监听
			btn.onclick = ()=>{
				//1.创建xhr实例对象
				const xhr = new XMLHttpRequest()

				//on  当xxx时候
				//ready 准备
				//state 状态
				//change 状态
				//xhr内部有5种状态,值分别为:0、1、2、3、4
				//xhr实例对象,在实例出来的那一刻状态就是0
				xhr.onreadystatechange = ()=>{
					if(xhr.readyState === 4){
						console.log(xhr.response);
						content.innerHTML = `<h3>${xhr.response}</h3>`
					}
				}

				//2.指定发送请求的:method、url
				xhr.open('GET','http://127.0.0.1:8080/test_get')
				
				//3.发送请求
				xhr.send()
			}
		</script>
	</body>
</html>

5.1、xhr的5种状态

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>2_xhr的5种状态</title>
		<style>
			#content{
				width: 300px;
				height: 100px;
				border: 1px solid black;
				margin-top: 10px;
			}
		</style>
	</head>
	<body>
		<h3>该页面是测试:xhr的5种状态</h3>
		<button id="btn">点我发送请求(原生js-ajax-get)</button>
		<div id="content"></div>
		<script type="text/javascript" >
			//获取按钮
			const btn = document.getElementById('btn')
			const content = document.getElementById('content')
			//给按钮绑定监听
			btn.onclick = ()=>{
				//1.创建xhr实例对象
				const xhr = new XMLHttpRequest()

				//xhr实例对象,在实例出来的那一刻状态就是0
				/* 
					xhr内部有5种状态,值分别为:0、1、2、3、4
							0:实例出来的那一刻状态就是0,初始状态。
							1:open已经调用了,但是send还没有调用,此时可以修改请求头内容。
							2:send已经调用了,已经无法修改请求头
							3:已经回来一部分数据了,小的数据会在此阶段一次性接收完毕,较大的数据有待进一步接收,响应头回来了。
							4:数据全部接收完毕
				*/
				xhr.onreadystatechange = ()=>{
					/* if(xhr.readyState === 1){
						xhr.setRequestHeader('demo',123) //配置请求头
					} */
					/* if(xhr.readyState === 2){
						xhr.setRequestHeader('demo',123) //配置请求头--报错
					} */
					if(xhr.readyState === 3){
						console.log('3时接收到的数据',xhr.response);
						console.log('3时接收到的响应头',xhr.getAllResponseHeaders());
					}
					if(xhr.readyState === 4 && (xhr.status >= 200 && xhr.status < 300)){
						console.log(xhr.response);
						content.innerHTML = `<h3>${xhr.response}</h3>`
					}
				}

				//2.指定发送请求的:method、url
				xhr.open('GET','http://127.0.0.1:8080/test_get')
				
				//3.发送请求
				xhr.send()
			}
		</script>
	</body>
</html>

5.2、ajax的get请求

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>3_ajax_get请求</title>
		<style>
			#content{
				width: 300px;
				height: 100px;
				border: 1px solid black;
				margin-top: 10px;
			}
		</style>
	</head>
	<body>
		<h3>该页面是测试:ajax_get请求</h3>
		<button id="btn">点我发送请求(原生js-ajax-get)</button>
		<div id="content"></div>
		<script type="text/javascript" >
			//获取按钮
			const btn = document.getElementById('btn')
			const content = document.getElementById('content')
			//给按钮绑定监听
			btn.onclick = ()=>{
				//1.创建xhr实例对象
				const xhr = new XMLHttpRequest()

				//绑定监听
				xhr.onreadystatechange = ()=>{
					if(xhr.readyState === 4 ){
						if(xhr.status >= 200 && xhr.status < 300){
							console.log(xhr.response);
							content.innerHTML = `<h3>${xhr.response}</h3>`
						}
					}
				}

				//#region 
				/* 
						1.形如:key=value&key=value 就是query参数的urlencoded编码形式
						2.形如:/xx/xxx/老刘/18 就是params参数
				*/
				//#endregion
				//2.指定发送请求的:method、url、参数
				// xhr.open('GET','http://127.0.0.1:8080/test_get?name=老刘&age=18') //携带query参数
				xhr.open('PUT','http://127.0.0.1:8080/test_put') //携带params参数
				
				//3.发送请求
				xhr.send()
			}
			 
		</script>
	</body>
	<!-- 
	  get请求 
	    1、query参数
			 key=value&key=value 就是query参数的urlencoded编码形式
	    2、params参数 
	 		 /xx/xxx/老刘/18 就是params参数 
			 	这里有个小疑问?
				都是路径上的拼接我怎么知道他是地址的拼接还是参数一般来说在服务器有特殊的写法
				例如node服务器后端接口的写法/getList/:name/:age.
				例如SpringBoot后端接口的写法@PathVariable("name") String name
				在vue路由传参的写法上也有对应的params传参例如 {path: '/search/:words', component: Search} 他是有点类似于node服务器的写法	
		3、vscode折叠
			 #region							
	-->
</html>

5.3、ajax的post请求

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>4_ajax_post请求</title>
		<style>
			#content{
				width: 300px;
				height: 100px;
				border: 1px solid black;
				margin-top: 10px;
			}
		</style>
	</head>
	<body>
		<h3>该页面是测试:ajax_post请求</h3>
		<button id="btn">点我发送请求(原生js-ajax-post)</button>
		<div id="content"></div>
		<script type="text/javascript" >
			//获取按钮
			const btn = document.getElementById('btn')
			const content = document.getElementById('content')
			//给按钮绑定监听
			btn.onclick = ()=>{
				//1.创建xhr实例对象
				const xhr = new XMLHttpRequest()

				//绑定监听
				xhr.onreadystatechange = ()=>{
					if(xhr.readyState === 4 ){
						if(xhr.status >= 200 && xhr.status < 300){
							console.log(xhr.response);
							content.innerHTML = `<h3>${xhr.response}</h3>`
						}
					}
				}

				//2.指定发送请求的:method、url、参数
				xhr.open('POST','http://127.0.0.1:8080/test_post')

				//追加响应头用于标识携带请求体参数的编码形式--urlencoded
				xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded')

				//追加响应头用于标识携带请求体参数的编码形式--json
				//xhr.setRequestHeader('Content-type','application/json')
				
				//3.发送请求
				const person = {name:'老刘',age:20}

				xhr.send('name=老刘&age=18') //携带urlencoded编码形式的请求体参数
				// xhr.send(JSON.stringify(person)) //携带json编码形式的请求体参数
			}
		</script>
	</body>
</html>
<!-- 
  我们在上一个案例中、介绍到get请求可以携带query 和params参数、那么在post请求中都可以带什么参数呢?
  在我们一般的认知概念中、post请求带的是请求体参数、其实不是的他既可以携带query和parmas,但是一般我们都是放到请求体里
  post请求
	1、query
	2、parmas参数
	3、body参数
		放到send里边就是请求体参数、携带的是urlencoded编码形式的请求体参数
		当然我们也可以携带json编码形式的请求体参数
		注意必须携带请求头
			xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded')
			xhr.setRequestHeader('Content-type','application/json')
	4、题外话	
	    联想我们后端的技术我们发现后端接口在接收数据的时候,有的时候他用了注解有时候没有用,这是因为
		编码形式的不同,一种是urlencoded 一种是json格式的,一般如果前端发送json格式那么我们后端就需要用注解
-->

5.4、复习git操作

接下来我们需要回顾下怎么操作git,在接触Es6之前,我们已经系统的学习过了如何操作git,当你电脑上已经安装git客户端,你可以通过cmd黑窗口进行git操作,windows10操作系统也有一个工具 Windows PowerShell ,也可以通过git客户端自带的两种工具一个是GIT GUI Here、GIT Bash Here,cmd黑窗口的兼容性比较好,因为他从xp那个年代他就存在了,比如看看C盘下都有什么文件,使用命令dir,那我可以在cmd里敲Linux命令嘛?不好意思这是不支持的的,那谁支持呢?windows10的PowerShell是支持的,这个东西最大的优势是原始的Windows的shell脚本支持,Linux的也支持,这个东西我们用的不是很多,因为这个东西有的时候全局安装一个东西他就中断了,他说你没有权限去访问,用的多的还是cmd,GitBashHere就可以理解为一个是一个赠品。都可以,但是最好不要在PowerShell里敲了,有的时候全局安装东西容易出现问题,我那选择的使用方式是另一款软件Open Terminur here,他是一个单独的软件,他的劣势是启动速度比较慢,优势在于非常的美观,可以像浏览器一样开多个标签页,也可以调试那个字体颜色大小。

一般我们新到公司了,人家肯定会给你git地址,我们使用git clone 地址克隆下来,进入到桌面怎么进?桌面叫做Desktop 使用命令 cd des 按下tab他就联想了mkdir test,git clone 克隆一个仓库, 存在一个依赖管理文件,npm的话就是npm i,yarn的话就直接安装所有依赖,接下来就是git pull origin master,拉取写代码,add 添加到暂存区,git commit -m ‘update’ git push推送代码,在使用git项目管理项目时候,最大问题就是在处理冲突,分支的合并

5.5、VsCode怎么操作git

冲突就是同一行位置上产生了不同的内容就是冲突

image-20241001160908342

更改移动到右边这是不对的,右箭头是还原块的意思,+号箭头是暂存块

左侧工具栏更改旁边有一个+好,可以把所有更改的文件添加到暂存区,跟 git add .效果一样

暂存的更改旁边有一个减号意思是从暂存区域给他撤回来

消息输入框、可以输入对应的提交信息,跟 git -m “提交了一个文件”,此时只是我们本地仓库管理了对应文件

在往上走一点有三个点,点击,会显示拉取 推送、克隆、提交、更改、拉取、推送等选项操作

常用的几个命令

clone init add commit push pull

5.6、怎么改VsCode快捷键及代码片段

小齿轮—>键盘快捷方式---->搜索对应的键

ctrl+w 改为向下复制行

小齿轮---->用户代码片段

html.json js.json a.vue

5.7、解析json数据

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>5_ajax_解析json数据</title>
		<style>
			#content{
				width: 300px;
				height: 100px;
				border: 1px solid black;
				margin-top: 10px;
			}
		</style>
	</head>
	<body>
		<h3>该页面是测试:ajax_解析json数据</h3>
		<button id="btn">点我发送请求(原生js-ajax-get)</button>
		<div id="content"></div>
		<script type="text/javascript" >
			const btn = document.getElementById('btn')
			const content = document.getElementById('content')

			btn.onclick = ()=>{
				//实例xhr
				const xhr = new XMLHttpRequest()

				//绑定监听
				xhr.onreadystatechange = ()=>{
					if(xhr.readyState === 4){
						if(xhr.status >= 200 && xhr.status <300){
							const {name,age,sex} = xhr.response
							content.innerHTML = (`
								<ul>
									<li>姓名:${name}</li>
									<li>年龄:${age}</li>
									<li>性别:${sex}</li>
								<ul>
								`)
						}
					}
				}
				
				//配置请求
				xhr.open('GET','http://127.0.0.1:8080/get_person')

				//responseType用于指定返回数据的格式
				xhr.responseType = 'json'

				//发送请求
				xhr.send()
			}
		</script>
	</body>
</html>

5.8、对象的连续结构赋值

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
     <script type="text/javascript">
         let  obj={a:1,b:{c:2}}
        //  const {c}=obj.b; //标准的解构赋值写法
         console.log(c);

         const {b:{c}}=obj
         console.log(c);//连续的机构赋值 react项目中会有这种写法
         
         //如何让c改个名字,重命名
         const {b:{c:value}}=obj
         console.log(value);

     </script>
</body>
</html>

5.9、ajax请求的异常与超时处理

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>7_ajax请求的异常与超时处理</title>
		<style>
			#content{
				width: 300px;
				height: 100px;
				border: 1px solid black;
				margin-top: 10px;
			}
		</style>
	</head>
	<body>
		<h3>该页面是测试:ajax请求的异常与超时处理</h3>
		<button id="btn">点我发送请求(原生js-ajax-get)</button>
		<div id="content"></div>
		<script type="text/javascript" >
			const btn = document.getElementById('btn')
			const content = document.getElementById('content')

			btn.onclick = function(){
				//实例xhr
				const xhr = new XMLHttpRequest()

				//绑定监听
				xhr.onreadystatechange = function(){
					if(xhr.readyState === 4){
						if(xhr.status >= 200 && xhr.status <300){
							const {name,age,sex} = xhr.response
							content.innerHTML = (`
								<ul>
									<li>姓名:${name}</li>
									<li>年龄:${age}</li>
									<li>性别:${sex}</li>
								<ul>
								`)
						}
					}
				}
				
				//配置请求
				xhr.open('GET','http://127.0.0.1:8080/get_person_delay')

				//responseType用于指定返回数据的格式
				xhr.responseType = 'json'

				//配置出错的回调
				xhr.onerror = ()=>{
					alert('当前网络不稳定,请稍后重试');
				}

				//超时时间
				xhr.timeout = 2000 

				//超时的回调
				xhr.ontimeout = ()=>{
					alert('网速不给力,请切换网络重试');
				}

				//发送请求
				xhr.send()
			}
		</script>
	</body>
</html>

6.0、取消请求

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>8_ajax取消请求</title>
		<style>
			#content{
				width: 300px;
				height: 100px;
				border: 1px solid black;
				margin-top: 10px;
			}
		</style>
	</head>
	<body>
		<h3>该页面是测试:ajax取消请求</h3>
		<button id="btn">点我发送请求(原生js-ajax-get)</button>
		<button id="btn2">取消请求</button>
		<div id="content"></div>
		<script type="text/javascript" >
			const btn = document.getElementById('btn')
			const btn2 = document.getElementById('btn2')
			const content = document.getElementById('content')
			let xhr 

			btn.onclick = ()=>{
				//实例xhr
				xhr = new XMLHttpRequest()

				//绑定监听
				xhr.onreadystatechange = function(){
					if(xhr.readyState === 4){
						if(xhr.status >= 200 && xhr.status <300){
							const {name,age,sex} = xhr.response
							content.innerHTML = (`
								<ul>
									<li>姓名:${name}</li>
									<li>年龄:${age}</li>
									<li>性别:${sex}</li>
								<ul>
								`)
						}
					}
				}
				
				//配置请求
				xhr.open('GET','http://127.0.0.1:8080/get_person_delay')

				//responseType用于指定返回数据的格式
				xhr.responseType = 'json'

				//配置出错的回调
				xhr.onerror = ()=>{
					alert('当前网络不稳定,请稍后重试');
				}

				//超时时间
				xhr.timeout = 2000 

				//超时的回调
				xhr.ontimeout = ()=>{
					alert('网速不给力,请切换网络重试');
				}

				//发送请求
				xhr.send()
			}
			
			btn2.onclick = ()=>{
				xhr.abort()
			}
		</script>
	</body>
</html>

5.1、避免重复发送请求

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>9_避免多次重复请求</title>
		<style>
			#content{
				width: 300px;
				height: 100px;
				border: 1px solid black;
				margin-top: 10px;
			}
		</style>
	</head>
	<body>
		<h3>该页面是测试:避免多次重复请求</h3>
		<button id="btn">点我发送请求(原生js-ajax-get)</button>
		<div id="content"></div>
		<script type="text/javascript" >
			const btn = document.getElementById('btn')
			const content = document.getElementById('content')
			let xhr 
			let isLoading

			btn.onclick = ()=>{
				if(isLoading) xhr.abort()
				
				//实例xhr
				xhr = new XMLHttpRequest()

				//绑定监听
				xhr.onreadystatechange = function(){
					if(xhr.readyState === 4){
						if(xhr.status >= 200 && xhr.status <300){
							isLoading = false
							const {name,age,sex} = xhr.response
							content.innerHTML = (`
								<ul>
									<li>姓名:${name}</li>
									<li>年龄:${age}</li>
									<li>性别:${sex}</li>
								<ul>
								`)
						}
					}
				}
				
				//配置请求
				xhr.open('GET','http://127.0.0.1:8080/get_person_delay')

				//responseType用于指定返回数据的格式
				xhr.responseType = 'json'

				//发送请求
				xhr.send()
				isLoading = true
			}
			
		</script>
	</body>
</html>

在绝对快的情况下,也不能保证发送的绝对是一次请求,但是防止大量的重复点击足够了、我们要优化就让这个按钮不能重复点击就好了

isLoading = false 提升下这个放置位置

5.2、测试Jquery封装的ajax

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>10_jQuery封装的ajax</title>
		<style>
			#content{
				width: 300px;
				height: 100px;
				border: 1px solid black;
				margin-top: 10px;
			}
		</style>
		<script type="text/javascript" src="./js/jquery.min.js"></script>
	</head>
	<body>
		<h3>该页面是测试:jQuery封装的ajax</h3>
		<button id="btn1">点我发送请求(jQuery-ajax-get)</button>
		<button id="btn2">点我发送请求(jQuery-ajax-post)</button>
		<div id="content"></div>
		<script type="text/javascript" >
			const btn1 = $('#btn1')
			const btn2 = $('#btn2')
			const content = $('#content')

			btn1.click(()=>{
				//使用jQuery发送ajax-get(完整版)
				$.ajax({
					url:'http://127.0.0.1:8080/test_jquery_get', //请求地址
					method:'GET',//请求方式(默认值是GET)
					data:{school:'atguigu'},//携带的数据
					dataType:'json',//配置响应数据格式
					timeout:2000,//指定超时的时间
					success:(result,reponseText,xhr)=>{
						console.log(result,reponseText,xhr);
						content.append(`<div>汽车名:${result.name},价格:${result.price}</div>`)
					},//成功的回调
					error:(xhr)=>{console.log('请求出错了',xhr);} //失败的回调
				})

				//使用jQuery发送ajax-get(精简版)
				/* $.get('http://127.0.0.1:8080/test_jquery_get',{school:'atguigu'},(data)=>{
					console.log(data);
					content.append(`<div>汽车名:${data.name},价格:${data.price}</div>`)
				},'json') */
			})

			btn2.click(()=>{
				//使用jQuery发送ajax-post(完整版)
				$.ajax({
					url:'http://127.0.0.1:8080/test_jquery_post', //请求地址
					method:'POST',//请求方式(默认值是GET)
					data:{school:'atguigu'},//携带的数据
					dataType:'json',//配置响应数据格式
					timeout:2000,//指定超时的时间
					success:(result,reponseText,xhr)=>{
						console.log(result,reponseText,xhr);
						content.append(`<div>汽车名:${result.name},价格:${result.price}</div>`)
					},//成功的回调
					error:(xhr)=>{console.log('请求出错了',xhr);} //失败的回调
				})

				//使用jQuery发送ajax-post(精简版)
				$.post('http://127.0.0.1:8080/test_jquery_post',{school:'atguigu'},(data)=>{
					console.log(data);
					content.append(`<div>汽车名:${data.name},价格:${data.price}</div>`)
				},'json')
			})

		</script>
	</body>
</html>

5.3、ajax的回调地狱问题

回调地狱是指一种不太好的编码形式,是一种套娃现象

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>11_演示回调地狱</title>
		<script type="text/javascript" src="./js/jquery.min.js"></script>
	</head>
	<body>
		<h3>该页面是测试:演示回调地狱(看代码)</h3>
		<button id="btn1">点我发送请求(jQuery-ajax-get)</button>
		<script type="text/javascript" >
			const btn1 = $('#btn1')

			btn1.click(()=>{
				//使用jQuery发送ajax-get(精简版)
				$.get('http://127.0.0.1:8080/test_jquery_get',{school:'atguigu'},(data)=>{
					console.log(data);
					$.get('http://127.0.0.1:8080/test_jquery_get',{school:'atguigu'},(data)=>{
						console.log(data);
						$.get('http://127.0.0.1:8080/test_jquery_get',{school:'atguigu'},(data)=>{
							console.log(data);
						},'json')
					},'json')
				},'json')
				
			})
		</script>
	</body>
</html>

5.4、什么是同源策略

  1. 同源策略是由Netscape提出的一个著名的安全策略,现在所有支持JavaScript 的浏览器都会使用这个策略。
  2. Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
  3. 所谓同源是指:协议,域名(IP),端口必须要完全相同 即:协议、域名(IP)、端口都相同,才能算是在同一个域里

5.5、为什么会有跨域这个问题?

原因是浏览器为了安全,而采用的同源策略(Same origin policy)

注意、同源策略是浏览器的一种限制

5.6、没有同源策略的危险场景

危险场景

有一天你刚睡醒,收到一封邮件,说是你的银行账号有风险,赶紧点进www.yinghang.com改密码。你着急的赶紧点进去,还是熟悉的银行登录界面,你果断输入你的账号密码,登录进去看看钱有没有少了,睡眼朦胧的你没看清楚,平时访问的银行网站是www.yinhang.com,而现在访问的是www.yinghang.com,随后你来了一条短信,钱没了,这个钓鱼网站做了什么呢?大概是如下思路:

<iframe id="baidu" src="https://www.baidu.com"></iframe>

<script type="text/javascript">
  const iframe = window.frames['baidu']
  const inputNode = iframe.document.getElementById('输入敏感信息的input的id')//现在是拿不到了,你能看到,但是你现在拿不到这里边的任何节点了
  console.log(inputNode.value)
</script>

非同源受到哪些限制

  1. Cookie不能读取;2、DOM无法获得;3、Ajax请求不能获取数据(能发是不能收)

5.7、JSONP解决跨域怎么解决跨域

要明确的是:JSONP不是一种技术,而是程序员“智慧的结晶”(利用了标签请求资源不受同源策略限制的特点)JSONP需要前后端人员互相配合。

前端页面写法

<body>
	  <button id="btn">按钮</button>
	  <script type="text/javascript">
	    var btn = document.getElementById('btn');
	    btn.onclick = function () {
	      //1. 创建一个script标签
	      var script = document.createElement('script');
	      //2. 设置回调函数
	      window.getData = function (data) {
	        console.log(data);//拿到数据
	      }
	      //3. 设置script标签src属性,填写跨域请求的地址
	      script.src = 'http://localhost:3000/jsonp?callback=getData';
	      //4. 将script标签添加到body中生效
	      document.body.appendChild(script);
	      //5.不影响整体DOM结构,删除script标签
	      document.body.removeChild(script);
	    }
	  </script>
</body>

后端写法

app.get('/jsonp', (req, res) => {
  //解构赋值获取请求参数
  const {callback} = req.query
  //去数据库查找对应数据
  const data = [{name: 'tom', age: 18}, {name: 'jerry', age: 20}];
  res.send(callback + '(' + JSON.stringify(data) + ')');
})

前端定义函数,后端返回数据的时候调用对用的函数,一切的一切都是因为你定义了对应的函数,这样后端传回来的值才能进行调用

jsonp解决跨域的原理就是绕开了xhr,借助script标签不受同源策略的影响,发送get请求,把数据给拿回来了,有一种前端定义函数,后端调用函数的感觉

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>Document</title>
	</head>
	<body>
		<h3>当前页面一定不要用服务器去打开,因为要制造跨域问题,用jsonp去解决</h3>
		<button id="btn">点我获取数据</button>
		<script type="text/javascript" >
			
			const btn = document.getElementById('btn')
			btn.onclick = ()=>{
				//1.创建script节点
				const scriptNode = document.createElement('script')
				//2.给节点指定src属性(请求地址)
				scriptNode.src = 'http://localhost:8080/test_jsonp?callback=peiqi'
				//3.将节点放入页面
				document.body.appendChild(scriptNode)
				//4.准备好一个函数
			 	window.peiqi = (a)=>{
					console.log(a);
				}
				//5.移除已经使用过的script节点
				document.body.removeChild(scriptNode)
			}
			//前端给后端发个信息,你小子发信息的时候记住了,那个函数的名字叫做,demo,后端说不行,你这么写的话你得请我吃烧烤,没有原因,想吃烧烤了
		</script>
		
	</body>
</html>

5.8、后台接口框架处理跨域问题

我是后端程序员,做java的处理跨域问题就非常的简单

1、我们有对应的@cors注解、或者配置SpringMVC的对应cors配置项、或者使用nginx解决跨域问题

2、使用vue的脚手架或者React脚手架的代理服务器(这个其实是webpack或者vite里边的一个模块提供的)

3、Node后端框架的处理:

res.set('Access-Control-Allow-Origin', 'http://localhost:63342');
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>测试cors解决跨域</title>
	</head>
	<body>
		<h3>当前页面一定不要用服务器去打开,因为要制造跨域问题,测试cors解决跨域</h3>
		<button id="btn">点我获取数据</button>
		<script type="text/javascript" >
			const btn = document.getElementById('btn')
			btn.onclick = ()=>{
				const xhr = new XMLHttpRequest()
				xhr.onreadystatechange = ()=>{
					if(xhr.readyState === 4){
						if(xhr.status === 200){
							console.log(xhr.response);
							console.log(xhr.getAllResponseHeaders());
						}
					}
				}
				xhr.open('PUT','http://localhost:8080/test_put')
				xhr.send()
			}
		</script>
		
	</body>
</html>

5.9、jquery封装的jsonp

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>Document</title>
		<script type="text/javascript" src="./js/jquery.min.js"></script>
	</head>
	<body>
		<h3>当前页面一定不要用服务器去打开,因为要制造跨域问题,jquery封装的jsonp</h3>
		<button id="btn">点我获取数据</button>
		<script type="text/javascript" >
			const btn = $('#btn')
			btn.click(()=>{
				$.getJSON('http://localhost:8080/test_jsonp?callback=?',{},(data)=>{
					console.log(data);
				})
			})
		</script>
		
	</body>
</html>

页面无刷新获取数据,让用户的体验更好,不用频繁的跳转页面

Access-Control-Allow-Origin

访问-控制-允许-源

Access-Control-Expose-Headers

访问-控制-暴漏-请求头

Access-Control-Allow-Methods

访问-控制-允许-方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/888310.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

windows配置C++编译环境和VScode C++配置(保姆级教程)

1.安装MinGW-w64 MinGW-w64是一个开源的编译器套件&#xff0c;适用于Windows平台&#xff0c;支持32位和64位应用程序的开发。它包含了GCC编译器、GDB调试器以及其他必要的工具&#xff0c;是C开发者在Windows环境下进行开发的重要工具。 我找到了一个下载比较快的链接&#…

Excel下拉菜单制作及选项修改

Excel下拉菜单 1、下拉菜单制作2、下拉菜单修改 下拉框&#xff08;选项菜单&#xff09;是十分常见的功能。Excel支持下拉框制作&#xff0c;通过预设选项进行菜单选择&#xff0c;可以避免手动输入错误和重复工作&#xff0c;提升数据输入的准确性和效率 1、下拉菜单制作 步…

硬盘数据恢复的方法有哪几种?9种妙招速览

在当今数字化时代&#xff0c;硬盘数据的安全至关重要。然而&#xff0c;数据丢失的情况时有发生&#xff0c;掌握硬盘数据恢复方法显得尤为重要。本文将详细介绍几种有效的硬盘数据恢复方法&#xff0c;帮助用户在遇到数据丢失问题时&#xff0c;能够迅速采取措施&#xff0c;…

LabVIEW提高开发效率技巧----使用动态事件

在LabVIEW开发过程中&#xff0c;用户交互行为可能是多样且不可预知的。为应对这些变化&#xff0c;使用动态事件是一种有效的策略。本文将从多个角度详细介绍动态事件的概念及其在LabVIEW开发中的应用技巧&#xff0c;并结合实际案例&#xff0c;说明如何通过动态事件提高程序…

github——指标统计

github——指标统计 它的作用特定项目统计首页展示 github-readme-stats是一个可以统计指定用户github指标的项目。可以使用此项目统计自己的github&#xff0c;用于首页展示。效果如图&#xff1a; 它的作用 它可以&#xff1a; 统计git操作统计账户编程语言构成比例解除githu…

sqli-labs less-13 post报错注入使用extractvalue

post提交报错注入 闭合方式及注入点 利用hackbar进行注入&#xff0c;构造post语句 unameaaa’passwdbbb&SubmitSubmit 页面报错&#xff0c;根据分析&#xff0c;闭合方式). 确定列数 构造 unameaaa’) or 11 # &passwdbbb&SubmitSubmit 确定存在注入 unameaaa’…

论文复现:Training on the Benchmark Is Not All You Need

文章目录 1 资料2 我的总结3 复现源码首先你需要有gpt的api接口安装&#xff1a;执行指令源码data_process.pyinference_logprobs.py 4 结果 1 资料 我复现的源码: https://github.com/Whiffe/Benchmark-leakage-detection/tree/main 官网源码&#xff1a;https://github.com…

【RAG】HiQA:一种用于多文档问答的层次化上下文增强RAG

前言 文档领域的RAG&#xff0c;之前的工作如ChatPDF等很多的RAG框架&#xff0c;文档数量一旦增加&#xff0c;将导致响应准确性下降&#xff0c;如下图&#xff1b;现有RAG方法在处理具有相似内容&#xff08;在面对大量难以区分的文档时&#xff09;和结构的文档时表现不佳…

【leetcode】125.验证回文串

思路&#xff1a; isPalindrome 函数&#xff1a; 使用两个指针 left 和 right 分别指向字符串的开始和结束。使用 isalnum 函数跳过非字母数字字符。使用 tolower 函数将字符转换为小写进行比较。如果在某一步比较中发现字符不相等&#xff0c;则返回 0&#xff08;false&…

Python进阶--函数进阶

目录 1. 函数多返回值 2. 函数多种传参方式 (1). 位置参数 (2). 关键字参数 (3). 缺省参数 (4). 不定长参数 3. 匿名函数 (1). 函数作为参数传递 (2). lambda匿名函数 1. 函数多返回值 def return_num():return 1# 返回1之后就不会再向下继续执行函数体return 2 resu…

gstreamer 内存 alloctor 介绍

文章目录 前言一、gstreamer 默认的内存 alloctor1. gstreamer 中默认的内存 allocator 为 GST_ALLOCATOR_SYSMEM (即SystemMemory)2. GST_ALLOCATOR_SYSMEM 申请内存实例二、gstreamer 目前支持的几种内存 alloctor1.GstDmaBufAllocator1.1 GstDmaBufAllocator 介绍1.2 GstDma…

Vue3轻松实现前端打印功能

文章目录 1.前言2.安装配置2.1 下载安装2.2 main.js 全局配置3.综合案例3.1 设置打印区域3.2 绑定打印事件3.3 完整代码4.避坑4.1 打印表格无边框4.2 单选框复选框打印不选中4.3 去除页脚页眉4.4 打印內容不自动换行1.前言 vue3 前端打印功能主要通过插件来实现。 市面上常用的…

基于springboot vue地方废物回收机构管理系统设计与实现

博主介绍&#xff1a;专注于Java&#xff08;springboot ssm 等开发框架&#xff09; vue .net php phython node.js uniapp 微信小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不…

GeoCue与Xer Technologies合作推动无人机测绘技术革新

GeoCue与Xer Technologies合作推动无人机测绘技术革新 近期,LiDAR测绘硬件和软件开发商GeoCue与瑞士长航时混合动力无人机制造商Xer Technologies AG携手合作,成功将GeoCue的TrueView 720 LiDAR和图像传感器集成至Xer X8无人机平台。这一里程碑式的合作不仅标志着无人机测绘技…

基于STM32的智能门锁控制系统设计

引言 本项目基于STM32微控制器设计了一个智能门锁控制系统&#xff0c;用户可以通过密码输入或指纹识别来控制门锁的开关。该系统集成了键盘、指纹传感器、舵机等外设&#xff0c;实现了门锁的安全、便捷控制&#xff0c;同时也具备了较强的扩展性。该项目展示了STM32在安防领…

某个应用的CPU使用率居然达到100%,我该怎么办?

摘至https://learn.lianglianglee.com/ CPU使用率 Linux 作为一个多任务操作系统&#xff0c;将每个 CPU 的时间划分为很短的时间片&#xff0c;再通过调度器轮流分配给各个任务使用&#xff0c;因此造成多任务同时运行的错觉。 为了维护 CPU 时间&#xff0c;Linux 通过事先定…

七、InnoDB数据存储结构

文章目录 1. 数据库的存储结构:页1.1 磁盘与内存交互基本单位:页1.2 页结构概述1.3 页的大小1.4 页的上层结构2. 页的内部结构2.1 第1部分:File Header(文件头部)和 File Trailer(文件尾部)2.1.1 File Header(文件头部)2.1.2 File tRAILER(文件尾部)2.2 第2部分:Fr…

【AIGC】通过OpenAi Canvas修改论文(附40条论文优化指令)

目录 1、用ChatGPT优化论文大纲和逻辑2、用ChatGPT充实论文内容3、用ChatGPT寻找案例和数据4、用ChatGPT检查语法和字词错误5、如何直接使用ChatGPT4o、o1、OpenAI Canvas6、OpenAI Canvas增强了啥&#xff1f;7、编程功能增强 在刚开始撰写学术论文时&#xff0c;很多小伙伴感…

深度学习之贝叶斯分类器

贝叶斯分类器 1 图解极大似然估计 极大似然估计的原理&#xff0c;用一张图片来说明&#xff0c;如下图所示&#xff1a; ​ 例&#xff1a;有两个外形完全相同的箱子&#xff0c;1号箱有99只白球&#xff0c;1只黑球&#xff1b;2号箱有1只白球&#xff0c;99只黑球。在一次…

LeetCode刷题日记之二叉树(六)

目录 前言二叉搜索树中的众数二叉树的最近公共祖先二叉搜索树的最近公共祖先总结 前言 又是学习LeetCode二叉树的新一天&#xff0c;今天还是接着学习一下二叉搜索树的内容&#xff0c;希望博主记录的内容能够对大家有所帮助 &#xff0c;一起加油吧朋友们&#xff01;&#x…