作者:江财第一深情(宇)
引言
今天,我们聊的是在javaScript中,如何用Ajax来向后端发出请求,实现前后端相互交流。相信有很多小伙伴们经常会遇到这样一种情况,当你第一次使用某种app时候,会让你注册一个账号,在这之前,需要填写一些信息。常见的:填写电话号码,然后点击获取一个验证码。那么这个验证码从何而来?其实这里有一个执行一个过程,当你点击获取验证码的时候,会向后端发送一个请求,然后后端返回一个数据到用户。那么,在javaScript,我们怎么向后端发送请求呢,让我们一起来探索一下吧!
什么是Ajax(定义)
Ajax,全称为Asynchronous JavaScript and XML(异步JavaScript与XML),是一种网页开发技术,它能够让网页无须刷新就能与服务器交换数据并更新部分内容。这意味着用户可以享受到更快、更流畅的网页体验,因为只有需要更新的数据会被请求和交换,而不是重新加载整个页面。
Ajax的工作流程
- 创建XMLHttpRequest对象:这是Ajax的核心组件,用于在后台与服务器交换数据。所有现代浏览器均内建了 XMLHttpRequest 对象。
Javascript
1var xhr = new XMLHttpRequest();
- 配置请求:在发送请求之前,需要设置请求的方法(GET、POST等)、URL以及是否异步执行等。
Javascript
1xhr.open('GET', 'example.php', true);
- 设置回调函数:使用
onreadystatechange
事件监听请求状态的变化。当请求完成且状态为200(表示成功)时,执行相应的处理函数。
Javascript
1xhr.onreadystatechange = function() {
2 if (xhr.readyState == 4 && xhr.status == 200) {
3 // 在这里处理服务器返回的数据
4 console.log(xhr.responseText);
5 }
6};
- 发送请求:调用
send()
方法发送请求。如果是POST请求,还需要将数据作为参数传递给该方法。
Javascript
1xhr.send(null); // 对于GET请求,直接发送null
2// 或者 xhr.send('param1=value1¶m2=value2'); // 对于POST请求
5.最后, 客户端收到响应数据后,在回调函数中处理这些数据,如更新DOM,从而实现页面的局部刷新。**
那么问题来了,为什么在代码中,突然跑出来 '4'和 '200'这两个数字呢,这两个数字有什么特殊的含义呢?
首先,我们要知道xhr.readyState 和xhr.status, xhr.readyState是 XMLHttpRequest(XHR)对象的一个属性,用于表示当前 AJAX 请求的生命周期中的不同状态
1 -- open执行
2 -- 请求发送出去,响应头被接受
3 -- 响应体正在解析
4 -- 解析完成
xhr.status
是 XMLHttpRequest(XHR)对象的另一个属性,用于表示服务器对请求所返回的HTTP状态码,当xhr.status
==200时,表示请求已成功处理。
所以‘4’ 和‘200’这两个数字不是凭空而来的
接下来,我们用Ajax的三种方法,实现一个获取电影列表的案例
第一种,用原生的XMLHttpRequest
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="btn">徐宇点击按钮获取电影列表</button>
<ul id="list">
<li></li>
</ul>
这个是一个简单的html结构,- <button id="btn">获取电影列表</button>
: 创建了一个按钮,文本为"获取电影列表"。id="btn"
为按钮分配了一个唯一的标识符,便于通过JavaScript来选择和操控这个元素。-
<li></li>
: 无序列表中的一个列表项(List Item)。在这个例子中,列表项是空的,预期通过JavaScript动态添加电影条目。
接下来我们来看JavaScript片段
<script>
let btn=document.getElementById('btn')
let ul=document.getElementById("list")
btn.addEventListener('click',()=>{
//朝一个接口发请求,获取到数据展示在页面上
let xhr=new XMLHttpRequest(); //创建一个ajax实例
xhr.open('GET','https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get',true) //配置发送的参数
xhr.send();
xhr.onreadystatechange = () =>{ //监听请求的过程
if(xhr.readyState ==4&&xhr.status==200){ //拿到了后端返回的数据
console.log(JSON.parse(xhr.responseText))
//展示在页面上
const movieList= JSON.parse(xhr.responseText).movieList
console.log(movieList);
for(let i=0; i<movieList.length;i++)
{
const li=document.createElement("li");
li.innerHTML=movieList[i].nm + "--" +movieList[i].star
ul.appendChild(li)
// movieList[i]
}
}
}
})
</script>
来解释一下这段代码
-
获取页面上的元素:
let btn = document.getElementById('btn')
获取id为"btn"的按钮元素。let ul = document.getElementById("list")
获取id为"list"的无序列表元素。
-
给按钮绑定点击事件监听器:
btn.addEventListener('click', ()=>{...})
当按钮被点击时,执行匿名箭头函数内的代码。
-
发起Ajax GET请求:
let xhr = new XMLHttpRequest()
创建一个新的XMLHttpRequest对象,用于发送Ajax请求。 -xhr.open('GET', 'https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get', true)
配置请求,指定请求方法为GET,请求的URL,以及请求是否异步(true表示异步)。xhr.send()
发送请求到服务器。
- 监听请求状态变化并处理响应:
-
xhr.onreadystatechange = ()=>{...}
设置一个事件处理器,当请求状态改变时执行。 -
if(xhr.readyState == 4 && xhr.status == 200)
判断请求是否完成(readyState == 4
)且服务器响应成功(status == 200
)。- console.log(JSON.parse(xhr.responseText))` 打印出服务器返回的原始JSON格式的响应数据。
-
解析响应数据并遍历电影列表:
-
const movieList = JSON.parse(xhr.responseText).movieList
将响应的JSON字符串转换为JavaScript对象,并提取出movieList
数组。 -
使用for循环遍历
movieList
数组: -
const li = document.createElement("li")
为每部电影创建一个新的<li>
元素。 -
li.innerHTML = movieList[i].nm + "--" + movieList[i].star
设置<li>
的内容为电影名称(nm
)和演员(star
)。 -
ul.appendChild(li)
将新创建的<li>
元素添加到无序列表(ul
)中。
最后展示一下效果
每当点击获取电影列表时,页面都会展示相关电影的信息
第二种,用jQuery
首先,我们需要导入jQuery库
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
下面是js代码
<button id="btn">徐宇点击按钮获取电影列表</button>
<ul id="list">
<li></li>
</ul>
<script>
let btn = document.getElementById('btn')
let ul = document.getElementById("list")
btn.addEventListener('click', () => {
$.ajax({
url:'https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get',
method:'GET',
data:{
username:'徐宇',
age:18
},
success:function(res)
{
console.log(res)
}
})
})
</script>
来解释一下这段代码
-
btn.addEventListener('click', () => {...})
: 为按钮添加了一个点击事件监听器。当按钮被点击时,执行括号内的匿名箭头函数。 -
在匿名函数内部,使用了jQuery的
$.ajax
方法来发起一个Ajax请求:url: 'https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get'
: 指定了Ajax请求的目标URL,这是一个模拟的电影列表API。method: 'GET'
: 指定请求的方法为GET。data: {username: '牛哥', age: 18}
: 发送到服务器的额外数据,虽然在这个上下文中API可能并不需要这些数据,但这里展示了如何携带数据。success: function(res) {console.log(res)}
: 成功获取到服务器响应时执行的函数,这里的res
是服务器返回的数据。当前示例中只是简单地将响应打印到控制台。
相比上一次那一种方法,这种是不是简单一点呢?但是现实生活中,我们不仅要获取到后端的数据,一般情况下,前端也需要向后端发送一个或者多个参数,所以,这两个方法显得不是很优雅。那么下面,我们再来介绍另外一种方法
fetch
<body>
<button id="btn">fetch获取电影列表</button>
<ul id="list"></ul>
<script>
let btn = document.getElementById('btn');
let ul = document.getElementById('list');
// 给按钮添加点击事件监听器
btn.addEventListener('click', () => {
// 使用 fetch API 发送 GET 请求
fetch("https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList?username='牛哥'&age=18")
.then((res) => {
// 当请求成功后,返回响应对象并将其解析为 JSON 格式
return res.json();
})
.then((data) => {
// 在第二个 then 中处理解析后的 JSON 数据
// console.log(data);
const movieList = data.movieList;
for (let i = 0; i < movieList.length; i++) {
const li = document.createElement('li');
li.innerText = movieList[i].nm + '--' + movieList[i].star;
ul.appendChild(li);
}
})
})
</script>
</body>
来解释一下这段代码
-
获取页面元素:
let btn = document.getElementById('btn')
获取ID为"btn"的按钮元素。let ul = document.getElementById('list')
获取ID为"list"的无序列表元素。
-
添加点击事件监听器:
btn.addEventListener('click', () => {...})
为按钮添加点击事件监听器,当按钮被点击时,执行匿名箭头函数内的代码。
-
发起网络请求:
- 使用
fetch
函数发送一个GET请求到指定的URL (https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList
),尝试携带查询参数 (username='牛哥'&age=18
)。注意,根据API的实际需求,这些查询参数可能并不必要或格式不正确,应根据API文档调整。
- 使用
-
处理响应:
-
.then((res) => {...})
第一个.then
处理fetch返回的Promise,其中res
是响应对象。return res.json()
将响应体解析为JSON格式。此方法返回一个新的Promise,允许链式调用下一个.then
。
-
-
处理数据并更新DOM:
-
第二个
.then((data) => {...})
在数据解析成功后执行,data
是解析后的JSON对象。const movieList = data.movieList;
从响应数据中提取电影列表。- 使用
for
循环遍历movieList
,为每个电影创建一个新的<li>
元素,并将其文本内容设置为电影的名字和演员信息。 ul.appendChild(li);
将新创建的<li>
元素添加到ul
元素中,实现电影列表的动态渲染。
-
在这里,我们可以在fetch里面,向后端传一些参数
fetch("https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList?username='牛哥'&age=18")
仔细看这段代码,传参数的语法是:
1.在地址的最后面,写一个 ?(问号),
2.然后写 参数名字:"你想要向后端传入的值" 如上面username="牛哥"
3.假如你想向后端传入多个参数,直接用&进行连接
那么,怎么知道向后端发送的参数有没有成功呢?我们在控制台里面点击网络,如果点击触发事件之后,吹出现了一个负载,并且参数的数据对了,说明发送成功了
最后,总结一下这三种方法的优缺点
XMLHttpRequest (XHR)
优点:
- 原生支持: 作为最早支持Ajax的原生JavaScript对象,几乎所有现代浏览器都支持。
- 广泛兼容: 支持多种请求类型(GET、POST、PUT、DELETE等)和多种数据格式。
- 灵活性高: 提供详细的请求和响应控制,包括设置请求头、超时、取消请求等。
缺点:
- 代码繁琐: 相比于Fetch和jQuery,编写XMLHttpRequest的代码较为冗长,需要手动处理各种状态和事件。
- 回调地狱: 异步处理依赖回调函数,可能导致代码难以理解和维护。
jQuery的Ajax方法
优点:
- 简化语法: 提供了更简洁的API,相比原生XHR减少了大量样板代码。
- 跨域支持: 自动处理跨域请求的CORS头部,简化跨源通信。
- 链式调用: 结合jQuery的链式操作,使得代码更易读。
- 强大的错误处理: 内置了良好的错误处理机制。
缺点:
- 库依赖: 需要引入整个jQuery库,即使你只需要使用Ajax功能,这可能增加页面体积。
- 过时风险: 随着现代前端框架和库的兴起,jQuery的使用逐渐减少。
Fetch API
优点:
- 现代化: 基于Promise,支持async/await,使得异步编程更加优雅和易于理解。
- 原生支持: 无需第三方库,现代浏览器均支持。
- 流式处理: 支持Response对象的Body作为ReadableStream,适用于处理大文件或实时数据。
缺点:
- 不支持老浏览器: IE不支持,对于需要兼容老旧浏览器的应用需要polyfill。
- 错误处理: 默认情况下,即使是404或500等HTTP错误也会当作成功处理,需要手动检查
response.ok
或使用try/catch来捕获错误。 - 缺少进度和超时选项: 不像XHR,Fetch原生不支持进度事件和超时设置。
总结
今天,我们了解了在js中,介绍了3种方法,如何向后端发送请求,并实现了一个获取电影列表的案例,并且分析了3种方法的优缺点。如果您觉得在这里,能获取到知识,希望多多支持一下