3_Ajax概述

1. Ajax概述

1.1 AJAX 简介

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


1.2 XML 简介

XML 可扩展标记语言。
XML 被设计用来传输和存储数据。
XML 和HTML 类似,不同的是HTML 中都是预定义标签,而XML 中没有预定义标签,
全都是自定义标签,用来表示一些数据。

比如说我有一个学生数据:
name = “孙悟空” ; age = 18 ; gender = “男” ;
用XML 表示:

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

现在已经被JSON 取代了。
{"name":"孙悟空","age":18,"gender":"男"}


1.3 AJAX 的特点

1.3.1 AJAX 的优点

1、可以无需刷新页面而与服务器端进行通信。
2、允许你根据用户事件来更新部分页面内容。

1.3.2 AJAX 的缺点

1、没有浏览历史,不能回退
2、存在跨域问题(同源)
3、SEO 不友好(页面中有些东西是ajax动态创建的,爬虫就爬不到)



2. HTTP相关问题

http(hypertext transport protocol)协议(超文本传输协议),协议详细规定了浏览器和万维网服务器之间互相通信的规则。

2.1 MDN 文档

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Overview

2.2 HTTP 请求交互的基本过程

image
1、前后应用从浏览器端向服务器发送HTTP 请求(请求报文)
2、后台服务器接收到请求后, 调度服务器应用处理请求, 向浏览器端返回HTTP响应(响应报文)
3、浏览器端接收到响应, 解析显示响应体/调用监视回调

2.3 HTTP 请求报文的结构

请求报文就是客户端向服务端发送请求。

1. 请求行部分

请求行包括三个部分:
第一个部分:请求类型(常见的有get、post)
第二个部分:url路径
第三个部分:http协议版本
如:"请求类型/url/http版本"
GET /product_detail?id=2

2、多个请求头

常用的请求头:
Host:
Cookie:
Content-type:
User-Agen:
...

3、空行

空行表示请求头结束

4. 请求体

可以有可以没有,get请求就没有。

下面就是一个完整的请求报文结构图:
image


2.4 HTTP 响应报文的结构

1. 行部分

请求行包括三个部分:
第一个部分:协议版本
第二个部分:响应状态码
第三个部分:响应状态字符串
如:"请求类型/url http版本"
HTTP /1.1 200 ok

2、响应头

常用的请求头:
Content-type:
Content-length:
Content-conding:
...

3、空行

空行表示请求头结束

4. 响应体

主要返回的结果

下面就是一个完整的响应报文结构图:
image

谷歌网络控制台查看通信报文步骤。
image



2.5 post 请求体参数格式

1、Content-Type: application/x-www-form-urlencoded;charset=utf-8
用于键值对参数,参数的键值用=连接, 参数之间用&连接
例如: name=%E5%B0%8F%E6%98%8E&age=12

2、Content-Type: application/json;charset=utf-8
用于 json 字符串参数
例如: {"name": "%E5%B0%8F%E6%98%8E", "age": 12}

3、Content-Type: multipart/form-data
用于文件上传请求

2.6 常见的响应状态码

200 OK 请求成功。一般用于GET 与POST 请求
201 Created 已创建。成功请求并创建了新的资源
401 Unauthorized 未授权/请求要求用户的身份认证
404 Not Found 服务器无法根据客户端的请求找到资源
500 Internal Server Error 服务器内部错误,无法完成请求

2.7 API 的分类

1、REST API: restful (Representational State Transfer (资源)表现层状态转化)
(1) 发送请求进行CRUD 哪个操作由请求方式来决定
(2) 同一个请求路径可以进行多个操作
(3) 请求方式会用到GET/POST/PUT/DELETE

2、非REST API: restless
(1) 请求方式不决定请求的CRUD 操作
(2) 一个请求路径只对应一个操作
(3) 一般只有GET/POST

2.9 区别 一般http请求 与 ajax请求

1、ajax请求 是一种特别的 http请求。

2、对服务器端来说, 没有任何区别, 区别在浏览器端。

3、浏览器端发请求: 只有XHR 或fetch 发出的才是ajax 请求, 其它所有的都是非ajax 请求。

4、浏览器端接收到响应
(1) 一般请求: 浏览器一般会直接显示响应体数据, 也就是我们常说的刷新/跳转页面
(2) ajax请求: 浏览器不会对界面进行任何更新操作, 只是调用监视的回调函数并传入响应相关数据


3. 原生AJAX 的基本使用 XHR

3.0 准备工作

3.0.1 安装node.js

http://nodejs.cn/

3.0.2 安装express(服务端框架)步骤:

https://www.expressjs.com.cn/

1、初始化环境
npm init --yes

2、下载express包
npm install express --save

1和2操作命令的cmd终端在文件夹最外层打开输入。
image

3、编写js代码

// 1. 引入express
const express = require('express');

// 2. 创建应用对象
const app = express();

// 3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
app.get('/', (request, response) => {
  //  设置响应体
  response.send("Hello Express");
});

// 4. 监听端口,启动服务
app.listen(8000, () => {
  console.log("服务已经启动, 8000 端口监听中...");
 })

4、运行js程序
node .\01express使用.js
注意:node 后面跟的是你创建的js文件,而且,启动它也是在你这个js文件的上一级文件夹右键打开的终端里启动,不是根目录的终端。上面这个js文件是占用了80端口,如果另一个js文件也要当作服务启动的话,那么就会显示端口报错的提示,所以要关闭窗口,直接到当前正在启动的node里面的终端cmd里面用快捷键ctrl+c即可关闭当前启动的端口。如:
image

启动成功如:
image

5、打开网页显示页面
image

6、谷歌浏览器内调试程序可以查看请求和响应
image


3.0.3案例

1、案例准备

创建一个文件夹:testcode,在里面创建html文件1gethtml.html,再创建js文件server.js,再右键 testcode文件夹,打开终端cmd,启动当前js。
image

1gethtml.html代码如下:
image

页面访问js
image


2、ajax基本操作(原生ajax写法)

在1gethtml.html里创建ajax

    <script>
        const btn=document.getElementsByTagName("button")[0];
        const result=document.getElementById("result");
        btn.onclick=function(){

            //XMLHttpRequest对象的readyState属性值: 0 - 未初始化,1 - open方法调用完毕,
            //2 - send方法调用完毕,3 - 服务端返回了部分结果,4 - 服务端返回了所有结果

            //1,创建对象
            const xhr=new XMLHttpRequest(); //xmlhttprequest  用于与服务器交换数据

            //2,初始化,设置请求方法和url,url是刚刚建立的server.js的监听端口地址
            xhr.open('get','http://127.0.0.1:8000/server');

            //3,发送该请求(可能是在tcp建立的第二次握手确认请求)
            xhr.send();

            //4,事件绑定(ajax回调函数),处理服务端返回的结果
            xhr.onreadystatechange=function(){
                //判断(等服务器返回的所有结果后再处理)
                if(xhr.readyState===4){
                    //判断响应状态码,200以上300以下为成功
                    if(xhr.status>=200&&xhr.status<300){
                        //处理响应报文结果:

                        //1、响应行:
                        console.log(xhr.status);//状态码
                        console.log(xhr.statusText);//状态字符串
                        //2、响应头:
                        console.log(xhr.getAllResponseHeaders());//所有响应头
                        //2、响应体
                        console.log(xhr.response);//所有响应头

                        result.innerHTML=xhr.response;
                    }      
                }
            }

        }
    </script>

开启server.js的监听。
image


2.1、ajax设置请求参数

直接在url后面传递
image

浏览器调试查看

image

服务端后台根据请求中的变量名就可以取得该变量的值
image


2.2、ajax发送post请求

html元素:
<div id="result"></div>
css:

#result{
            width:200px;
            height:100px;
            border:solid 1px rebeccapurple; 
        }

js:

    <script>
        //获取元素对象
        const result=document.getElementById("result");
        //绑定事件
        result.addEventListener("mouseover",function(){
           //1、创建对象
           const xhr=new XMLHttpRequest();
           //2、初始化 设置请求类型与url
           xhr.open("POST","http://127.0.0.1:8000/server");

           //3,发送
           xhr.send();

           //4,事件绑定
           xhr.onreadystatechange=function(){
               if(xhr.readyState==4){
                   if(xhr.status>=200&&xhr.status<300){
                       result.innerHTML=xhr.response;

                   }

               }
           }
        });        
    </script>

js的端口服务框架里要创建post方法,不然通过这个路由也访问不到服务端,修改了服务端口要重新启动服务端口,不然还是会报错。
image


2.3、ajax发送post请求,设置请求体的数据

image


2.4、ajax发送post请求,设置请求头信息

设置请求头必须在open后,send前,如:

           //1、创建对象
           const xhr=new XMLHttpRequest();
           //2、初始化 设置请求类型与url
           xhr.open("POST","http://127.0.0.1:8000/server");
           //第一个参数,头的名字,第二个参数,头的值。
           xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
           //Content-Type:用来设置请求体内容的类型
           //application/x-www-form-urlencoded:固定写法,设置参数查询字符串的类型。

浏览器查看这个请求报文,可以看到里面有添加的请求报头信息
image

也可以自定义请求头:如,
image
不过在提交请求的时候会报错,因为我们在请求过程中添加了自定义的请求头,而如果是预定义的头就不会报错。
image

解决方法:后端服务端口里加一个响应头:
image

但是,这样还是不能用:他会向后端发送options类型的请求
image
再将服务端的响应方法改为all
image
这样就可以接收任意类型的请求了
image


2.5、服务端发送json数据

更改一下服务器的配置,修改下url,让页面访问这个方法返回json,注意,response只能返回字符串和buffer,所以要将json对象转为字符串
image

前端接收并且转为js的对象
image

也可以不手动转,只需要把请求头里设置数据格式给服务器
image
这样就可以不用手动转了,也可以用返回的响应体的数据
image


2.6、ajax请求超时与网络异常

现在客户端的方法里设置延时器,故意让响应延迟3秒。
image

客户端js里设置超时时间2秒
image

调用事件,用ajax向服务器发请求,会超时,并且取消这次请求。
image

超时回调,超时有个回调函数,在超时时候会触发。
image

网络异常回调:
image
通过浏览器设置网络为离线状态可以触发该回调:如
image


2.7、ajax取消请求

在ajax请求过程中,服务器还没有把响应回来之前,可以手动取消这次请求。
通过XMLHttpRequest对象的abort方法进行取消
image


2.8、ajax重发发送请求

点击第一个按钮,点击一次就会创建一个请求,如果用户疯狂点击,这个时候就会向服务器发送大量的相同的请求,也就是客户端频繁发请求服务器要频繁处理的问题。
解决思路 ,点这个按钮点击发请求的时候,看看之前有没有相同请求正在发送,如果有,就把之前没有完成的请求给取消掉 ,然后就发送一个新的,这样这个按钮不管点击多少次,都只有一个请求。
image

这样用户疯狂点击,前面相同请求也会被取消掉
image


3.0.4 安装nodemon自动重启工具

每次修改了node服务端都要重新启动端口,有的麻烦,可以安装nodemon自动重启工具自动重启。
首先,停止当前cmd运行的node,然后在cmd里输入指令即可安装。

文件内容有修改自动重新启动服务
https://www.npmjs.com/package/nodemon

1、安装
npm install -g nodemon

2、启动服务
要启动那个node服务器就在那个的cmd终端里启动即可。
ndoemon 你的后台服务脚本全名
如果系统禁止运行脚本可以到系统设置->更新与安全->打开开发人员选项->选择PowerShell的对号点击应用。
如果vscode不能加载nodemon解决办法:1.管理员身份打开powerShell 2.输入set-ExecutionPolicy RemoteSigned 3 选择Y 或者A ,就好了。

未对文件 C:\Users\Admin\AppData\Roaming\npm\nodemon.ps1 进行数字签名。无法在当前系统上运行该脚本。在node mon前加一个npx即可。
image



3.2 AJAX 请求状态

xhr.readyState 可以用来查看请求当前的状态
https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/readyState
image

image


3.3 API总结

image



4. jQuery 中的AJAX

4.1 get 请求

$.get(url, [data], [callback], [type])
url:请求的URL 地址
data:请求携带的参数
callback:载入成功时回调函数
type:设置返回内容格式,xml, html, script, json, text, _default

4.2 post 请求

$.post(url, [data], [callback], [type])

4.3 通用方法

$.ajax({
	// url
	url: 'http://127.0.0.1:8000/jquery-server',
	// 参数
	data: {a:100, b:200},
	// 请求类型
	type: 'GET',
	// 响应体结果
	dataType: 'json',
	// 成功的回调
	success: function(data){console.log(data);},
	// 超时时间
	timeout: 2000,
	// 失败的回调
	error: function(){console.log('出错拉~');},
	// 头信息
	headers: {
		c: 300,
		d: 400
	}	
})


5.使用js的fetch函数发送ajax请求

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



6. 跨域

6.1 同源策略

同源策略(Same-Origin Policy)最早由Netscape 公司提出,是浏览器的一种安全策略。
同源: 协议、域名、端口号必须完全相同。
跨域: 违背同源策略就是跨域。

同源例子:

新建一个服务端口9000:在这里面的/home路由里面,返回一个网页资源。并且开启这个服务端口。
image
然后再浏览器上请求这个路由,就会返回一个网页
image

1gethtml.html网页如下:只有一个按钮
image
给这个网页的按钮绑定一个单击事件,让它发送请求请求服务端口9000里的/data路由
image
可以看到这个路由返回的数据。
image

上面客户端请求一个服务器,服务器返回回来一个网页资源,这个网页资源里面的某些事件触发的请求如果是向同一个服务器的同一个端口发送的请求 ,这就是同源。


跨域源例子:

还是按照上面的例子,浏览器地址栏访问服务端口9000里面的/home路由,返回一个网页资源。

新建一个端口服务9500,并新建一个路由方法/data2,里面返回“用户数据2”
image

修改网页按钮的js,让其向9500端口发送请求。
image

可以看到返回的结果:
image

这个就是跨域访问了。里面的事件向另一个服务器发送请求(同一个服务器的不同端口也是跨域),就是跨域。
跨域访问的服务端里要允许跨域才可以,也可以只让某一个端口的用户访问。
image
如果是*星号,就表示允许所有的请求访问。


6.2 如何解决跨域

6.2.1 JSONP

1) JSONP 是什么

JSONP(JSON with Padding),是一个非官方的跨域解决方案,纯粹凭借程序员的聪明
才智开发出来,只支持get 请求。

2) JSONP 怎么工作的?

在网页有一些标签天生具有跨域能力,比如:img link iframe script。
JSONP 就是利用script 标签的跨域能力来发送请求的。

3) JSONP 的使用

1,用script来跨域。
在页面里用script标签写一个函数。
image

2,后端服务响应一个调用上个script里的函数的js代码回去,这样就等于跨域传输了数据(script的 返回结果要是一个js代码,不然前端浏览器的js引擎识别不了)。服务端返回的结果是一个函数调用,这个函数的实参就是服务端想给客户端返回的数据。这个函数客户端一定要提前声明好,不然响应回去到客户端就会报错。
image

这就是jsonp实现跨域的原理(就是返回函数调用)。

注意:页面是访问本地服务器响应回来的网页资源,也就是file协议。
image

而下面script标签的请求是一个http协议,所以它们是跨域的。
image

_dirname是nodejs里面用来获取绝对路径的

跨域是表示,不同服务之间不能进行数据传输。而使用原有可以跨域的标签,打破了跨域,进行数据传递。前端向后端请求返回值,返回值拿来干啥,最终是作为参数传给函数处理的。把函数名给后端,后端返回一个函数调用语句到前端执行。不同服务之间不能进行数据传输。而使用原有可以跨域的标签,打破了跨域,进行数据传递。


ajax原生实践

页面的输入框失去焦点后向服务端发送请求,验证用户名是否存在,服务端响应调用函数的js字符串。
html和js
image

后端,假校验。
image

效果:
image


jQuery 中的JSONP
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>Title</title>
	</head>
	<body>
		<button id="btn">按钮</button>
		<ul id="list"></ul>
		<script type="text/javascript" src="./jquery-1.12.3.js"></script>
		<script type="text/javascript">
			window.onload = function () {
				var btn = document.getElementById('btn')
				btn.onclick = function () {
					$.getJSON("http://api.douban.com/v2/movie/in_theaters?callback=?",function(data) {
						console.log(data);
						//获取所有的电影的条目
						var subjects = data.subjects;
						//遍历电影条目
						for(var i=0 ; i<subjects.length ; i++){
							$("#list").append("<li>"+
							subjects[i].title+"<br />"+
							"<img src=\""+subjects[i].images.large+"\" >"+
							"</li>");
						}
					});
				}
			}
		</script>
</body>
</html>



6.3 CORS

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

1) CORS 是什么?

CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS 是官方的跨域解决方
案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持
get 和post 请求。跨域资源共享标准新增了一组HTTP 首部字段,允许服务器声明哪些
源站通过浏览器有权限访问哪些资源

2) CORS 怎么工作的?

CORS 是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应
以后就会对响应放行。

3) CORS 的使用

主要是服务器端的设置:

router.get("/testAJAX" , function (req , res) {
	//通过res 来设置响应头,来允许跨域请求
	//res.set("Access-Control-Allow-Origin","http://127.0.0.1:3000");
	res.set("Access-Control-Allow-Origin","*");
	res.send("testAJAX 返回的响应");
});

posted @   青仙  阅读(82)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示