Ajax是可以用来与服务器进行通讯的一种技术,它可以在不刷新页面的情况下进行异步通讯并获得返回结果。
Ajax常用的请求方式有两种,GET和POST,接下来将详细给出这两种请求方式的异同,以及Ajax使用时需要注意的地方。
1 GET请求
get请求一般用在向服务器请求某些资源,例如请求一段文章,或者一张图片等等。
下面是完整的get请求的方式 我们可以看到,在获得XMLHttpRequest对象的时候我们进行了一个判断,这是因为
所有现代浏览器 (IE7+、Firefox、Chrome、Safari 以及 Opera) 都内建了 XMLHttpRequest 对象,
而IE6或以下的需要用到ActiveXObject才能构建,所以需要进行判断,不过这个判断不加似乎也没事,因为现在几乎不可能有人
使用IE6以下的浏览器了
let url = "http://localhost/StarRing/public/StarRing.php/StarRing/Articles/AjaxGet";
//1 定义xmlHttpRequset对象
let xmlHttp;
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
} else if (window.ActiveXObject) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
//2 设置请求方式以及URL 第三个参数表示是否进行异步请求 默认为true,若写个false则是同步请求
//不过一般没人会这么做
xmlHttp.open("GET", url, true);
//3 设置监听请求状态变化的函数
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
let responseText = JSON.parse(xmlHttp.responseText);
console.log(responseText);
}
};
//4 发送请求
xmlHttp.send();
我们来看看请求结果,我们可以看到,已经请求到了数据,这里需要注意,我请求的是我自己的Thinkphp后台,你们也可以去请求自己的后台。
2 POST
大家可以看到 post请求其实和get请求基本类似 不过需要设置请求头而已,这一步get请求不需要,并且大家应该注意到了,我的send里面写了个参数 "name=张三" 这是因为我的php后台需要收一个参数,而这也正是post请求的一个传参的方式,这里我要强调的是,ajax默认不能发送json数据,它post的传参数是以键值对的形式存在的
例如 :"name=zhangsan&age=17&sex=1"
多个参数使用 "&" 符号拼接
let url = "http://localhost/StarRing/public/StarRing.php/StarRing/Articles/AjaxPost";
//1 定义xmlHttpRequset对象
let xmlHttp;
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
} else if (window.ActiveXObject) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
//2 设置请求方式以及URL
xmlHttp.open("POST", url);
//3 设置请求头 这一步只有post请求需要 而get请求不需要
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
//4 设置监听请求状态变化的函数
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
let responseText = JSON.parse(xmlHttp.responseText);
console.log(responseText);
}
};
//5 发送请求
xmlHttp.send('name=张三');
来看看返回结果
3 状态码
大家可能注意到了,无论是post还是get,它都需要设置一个监听状态变化的函数,这是做什么呢?
这是因为ajax在请求的开始到结束是有自己的状态的。
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
let responseText = JSON.parse(xmlHttp.responseText);
console.log(responseText);
}
};
我们可以看到,判断了两种状态,这里readyState是ajax的准备状态,而status是http的响应状态码
readyState状态码
0 表示请求未初始化
1 已经与服务器建立好了链接
2 请求已经接受
3 正在处理请求
4 请求已经完成了,并且已将接收到了响应数据
HTTP的状态码
200 表示成功
304 请求成功 304和200都表示请求成功,只不过304请求的缓存数据
403 表示服务器拒绝请求
404 表示服务器地址未找到,这一般是服务器未开启,或请求地址有误
500 表示服务器的内部错误,这一般是服务的参数有误,或服务器代码写错了
这也就是我为什么在判断状态变化时,只有ajax的准备状态为4并且http的响应是200才算请求成功的原因。
4 踩坑
刚刚说了状态变化,现在我要告诉大家这里其实有个坑,如果我们在监听状态变化时,不仅仅写了 if 还加了 else子句的话,那么你的代码就可能会出现无法想象的错误,并且你可能很难找到
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
let responseText = JSON.parse(xmlHttp.responseText);
console.log(responseText);
}else{
//请求失败的操作
console.log("请求失败了")
}
};
我们可以这样请求一下,看看会返回什么
很奇怪,明明请求到了数据,但是请求失败的状态判断他也输出了,这是为什么呢?
其实主要是因为状态变化所导致的,我们需要明白一点
xmlHttp.onreadystatechange 这个函数,它是用来监听状态变化的函数,注意是状态变化,而我们刚刚说了,ajax有5种状态,也就是说它的状态会变四次
0 1
1 2
2 3
3 4
我们直接写个请求 ,来看看这四次是怎么变化的,大家可以看到,我总共在三个地方打印了状态的变化,第一处是刚刚创建时,
第二处是设置请求后时,第三处是在监听状态变化的函数里,这三处我用 A B C来标明
let url = "http://localhost/StarRing/public/StarRing.php/StarRing/Articles/AjaxGet";
//1 定义xmlHttpRequset对象
let xmlHttp;
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
} else if (window.ActiveXObject) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
console.log("A-->",xmlHttp.readyState);
//2 设置请求方式以及URL 第三个参数表示是否进行异步请求 默认为true,若写个false则是同步请求
//不过一般没人会这么做
xmlHttp.open("GET", url, true);
console.log("B-->",xmlHttp.readyState);
//3 设置监听请求状态变化的函数
xmlHttp.onreadystatechange = function () {
console.log("C-->",xmlHttp.readyState);
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
let responseText = JSON.parse(xmlHttp.responseText);
console.log(responseText);
}else{
//请求失败了
console.log("失败了");
}
};
//4 发送请求
xmlHttp.send();
然后我们来看看请求结果
结果一目了然,状态变化2和3和4都在同一个地方输出的,我们可以看到它的前缀都是 C-->,这也就是为什么我们写了else时,它会先执行两次else里面的内容,因为状态2 和 3 它也会进入到监听状态变化的函数中去,所以此时就会出现请求到了数据,但是失败的判断也会执行
所以,这是错误的例子
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
let responseText = JSON.parse(xmlHttp.responseText);
console.log(responseText);
}else{
//请求失败了
console.log("失败了");
}
};
正确的操作应该是这样
这样就可以完美的监听到请求到底是成功了,还是失败了
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState === 4) {
if(xmlHttp.status===200){
let responseText = JSON.parse(xmlHttp.responseText);
console.log(responseText);
}else{
//请求失败了
console.log("失败了");
}
}
};
我们可以看看,改成正确的操作之后的返回结果
可以看到 ,没有输出请求失败了。。
5 跨域
先来看看这个错误
有些同学按照我刚刚的代码进行请求,可能会出现这种错误,很懵逼,明明代码没错,这是为什么呢,
这其实就是我们所说的跨域问题,那什么是跨域呢?
跨域本质上是由浏览器的同源策略所导致的问题,什么是同源策略,同源策略是浏览器的一种安全机制,
同源策略是客户端脚本(尤其是Javascript
)的重要的安全度量标准。它最早出自Netscape Navigator2.0
,其目的是防止某个文档或脚本从多个不同源装载。
这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议。 指一段脚本只能读取来自同一来源的窗口和文档的属性。
若协议 域名 端口 中有一个不同,就会出现跨域问题。
那么,为什么要有同源策略,我们举例说明:比如一个黑客程序,他利用Iframe
把真正的银行登录页面嵌到他的页面上,当你使用真实的用户名,密码登录时,他的页面就可以通过Javascript
读取到你的表单中input
中的内容,这样用户名,密码就轻松到手了。
好,现在来说说怎么解决,我这里是直接在php后台设置了一个请求头,
public function AjaxPost(){
header('Access-Control-Allow-Origin:*');
$name = input('name');
$age = input('age');
echo json_encode( array("code"=>1,"msg"=>"post请求--".$name."---".$age));
}
没错 就是这段代码,它的意思大概就是允许所以客户端访问
header('Access-Control-Allow-Origin:*');
当然 解决办法不止这一种
jsonp、 iframe、window.name、window.postMessage、服务器上设置代理页面
这些方法都可以解决跨域问题。
好了,就写到这
来源:CSDN
作者:贝尔格尔屌丝
链接:https://blog.csdn.net/tdl081071tdy/article/details/103650703