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

news2024/11/18 17:31:04

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.coloradmin.cn/o/2184125.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

将脚本编译为pyd文件

Python虽然作为一种解释性语言&#xff0c;通常是使用解释器处理脚本的方式完成工作&#xff0c;但是也具有和很多其他诸如C、C#语言等类似的方式&#xff0c;可以将.py文件编译为*.pyd文件&#xff0c;即Python动态链接库文件。 关于动态链接库的优缺点这里就不展开细说了&…

Android Studio Dolphin 中Gradle下载慢的解决方法

我用的版本Android Studio Dolphin | 2021.3.1 Patch 1 1.Gradle自身的版本下载慢 解决办法&#xff1a;修改gradle\wrapper\gradle-wrapper.properties中的distributionUrl 将https\://services.gradle.org/distributions为https\://mirrors.cloud.tencent.com/gradle dis…

【测试类文档整理】软件项目测试方案(word)

1. 引言 1.1. 编写目的 1.2. 项目背景 1.3. 读者对象 1.4. 参考资料 1.5. 术语与缩略语 2. 测试策略 2.1. 测试完成标准 2.2. 测试类型 2.2.1. 功能测试 2.2.2. 性能测试 2.2.3. 安全性与访问控制测试 2.3. 测试工具 3. 测试技术 4. 测试资源 4.1. 人员安排 4.…

查缺补漏----程序查询方式和中断方式计算题

1.程序查询方式 总结下来就是&#xff1a; 必须在外设传输完端口大小的数据时访问端口&#xff0c;以防止数据未被及时读出而丢失。 占CPU总时间&#xff1a;就是某段时间内设备用了多少时钟周期/PCU有多少个时钟周期 CPU的时钟周期数&#xff1a;就看主频&#xff0c;主频表示…

记录Mybatis分页查询排序问题: Encountered unexpected token: “and“ “AND“

通过Page.addOrder设置了字段排序 执行的时候在 com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor#autoCountSql 方法中执行 CCJSqlParserUtil.parse Select select (Select) CCJSqlParserUtil.parse(sql);报错&#xff1a; failed to concat o…

YOLOv1–v11: 版本演进及其关键技术解析

最新消息&#xff1a;Yolo11发布最新版本2024.10 YOLO (You Only Look Once) 是一种高效的目标检测算法&#xff0c;自其初代发布以来&#xff0c;经过多次迭代&#xff0c;逐步提升了检测速度和精度。本文将详细介绍 YOLO 从 v1 到 v11 的各个版本&#xff0c;涵盖每个版本的发…

高性价比PCB分板机高速主轴SycoTec 4025 HY

德国 SycoTec 4025 HY 迷你型高速主轴以其悠久的历史、卓越的性能、良好的散热和长寿命&#xff0c;成为PCB分板的高性价比选择。 一、4025 HY亮点 1.悠久历史与 拥有 50 多年的应用历史&#xff0c;被称为 “主轴之母”&#xff0c;充分证明了其在行业中的可靠性和稳定性。 …

人工智能 | 手工测试用例转Web自动化测试生成

简介 在传统编写 Web 自动化测试用例的过程中&#xff0c;基本都是需要测试工程师&#xff0c;根据功能测试用例转换为自动化测试的用例。市面上自动生成 Web 或 App 自动化测试用例的产品无非也都是通过录制的方式&#xff0c;获取操作人的行为操作&#xff0c;从而记录测试用…

迎国庆,开源完全免费工作流引擎AntFlow 0.9最强版本发布,支持tidb,提升易用性and more...

AntFlow是一款前端仿钉钉的企业级工作流引擎。后端既可嵌入到现有业务系统&#xff0c;也可以做为独立的流程引擎中台部署&#xff08;SAAS模式&#xff09;。嵌入业务系统模式已经在笔者所在企业使用多年&#xff0c;功能丰富&#xff0c;能适多种国产办公场景&#xff1b;简单…

sql-labs靶场第一关测试报告

目录 一、测试环境 1、系统环境 2、使用工具/软件 二、测试目的 三、操作过程 1、寻找注入点 2、注入数据库 ①Order by判断列数 ②判断回显地方 ③爆库&#xff0c;查看数据库名称 ④爆表&#xff0c;查看security库的所有表 ⑤爆列&#xff0c;查看users表的所有…

【CKA】五、网络策略–NetworkPolicy

5、配置网络策略–NetworkPolicy 1. 考题内容&#xff1a; 2. 答题思路&#xff1a; 1、根据题目分析要创建怎样的网络策略 2、按题目要求查看ns corp-net的label 3、编写yaml&#xff0c;其中注意 namespace、label、port 3. 官网地址&#xff1a; https://kubernetes.io/…

【EXCEL数据处理】000011 案列 EXCEL带有三角形图标的单元格转换

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 【EXCEL数据处理】000011 案列 EXCEL带有三角形图标的单元格转换。使用…

数据结构-4.3.串的存储结构

一.串的顺序存储&#xff1a; 1.静态数组会由系统自动回收&#xff1b;动态数组需要手动回收&#xff1b; 2.优点&#xff1a;随机存取&#xff0c;可以立即找到所需的字符&#xff1b;缺点&#xff1a;插入和删除较麻烦&#xff1b; 3.串的顺序存储方案&#xff1a; 对于方…

双指针--收尾的两道题

双指针 (封面起到吸引读者作用&#xff0c;和文章内容无关哈&#xff0c;但是文章也是用心写的&#xff09; 三数之和 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums…

面向代理的从单体到基于服务架构的转变的好处

论文标题&#xff1a;《Benefits of Agent-Oriented Transitioning from Monolithic To Service-Based Architectures》 作者信息&#xff1a; Daniel-Costel Bouleanu, University of Craiova, Romania; Polytechnic of Bari, ItalyMarco Alfredo Loaiza Carrillo, Universi…

根据视频id查询播放量

声明&#xff1a;文章仅用于学习交流,如有侵权请联系删除 如何根据视频ID查询视频的播放数量 在数字化时代&#xff0c;视频内容的消费已成为人们日常生活的重要组成部分。无论是社交媒体平台上的短视频&#xff0c;还是视频分享网站上的长视频&#xff0c;了解视频的播放数量…

TryHackMe 第5天 | Pre Security (四)

该学习路径讲解了网络安全入门的必备技术知识&#xff0c;比如计算机网络、网络协议、Linux命令、Windows设置等内容。过去三篇已经对前三块内容进行了简单介绍&#xff0c;本篇博客将记录 Windows设置 部分。 Windows Fundamentals Part 1 对于 Windows &#xff0c;肯定会感…

只需10秒,昂首资本发现短线交易4个优点

在金融市场&#xff0c;短线交易已经成为投资者追求高效收益的重要工具。那么&#xff0c;这种交易的本质究竟是怎样的&#xff1f;以下是昂首资本对短线交易的深入解析&#xff0c;以及其优缺点的详细分析。 短线交易的本质可以这样描述&#xff1a;交易会有相当小的止损&…

LeetCode 983.最低票价

在一个火车旅行很受欢迎的国度&#xff0c;你提前一年计划了一些火车旅行。在接下来的一年时间里&#xff0c;你要旅行的日子将以名为 days 的数组给出。每一项是一个 1 到 365 的整数。 火车票有三种不同的销售方式&#xff1a; 一张为期一天的通行证售价为cost[0]美元 一张为…

Stable Diffusion绘画 | 来训练属于自己的模型:素材准备篇

首先要说明的是&#xff0c;模型训练&#xff0c;需要显卡持续不间断地一致运行&#xff0c; 快则0.5-1小时左右&#xff0c;慢的话可能需要跑上几小时&#xff0c;甚至是几天&#xff0c; 原因跟显卡的配置和训练设置参数都有关系。 模型训练与显卡配置&#xff1a; 训练 L…