https://www.jianshu.com/p/a37cd239db4e
https://segmentfault.com/a/1190000004322487#articleHeader16
下面是我自己整理的一张xhr
相关事件触发条件表,其中最需要注意的是 onerror
事件的触发条件。
GET:
向服务器发送的地址+?数据名=+数据值+&数据名=+数据值,例子:
var url = "xxx.php"+"?username="+username+"&password="+password;
POST:
xhr.send("name=Alex&age=16");
事件 | 触发条件 |
---|---|
onreadystatechange | 每当xhr.readyState 改变时触发;但xhr.readyState 由非0 值变为0 时不触发。 |
onloadstart | 调用xhr.send() 方法后立即触发,若xhr.send() 未被调用则不会触发此事件。 |
onprogress | xhr.upload.onprogress 在上传阶段(即xhr.send() 之后,xhr.readystate=2 之前)触发,每50ms触发一次;xhr.onprogress 在下载阶段(即xhr.readystate=3 时)触发,每50ms触发一次。 |
onload | 当请求成功完成时触发,此时xhr.readystate=4 |
onloadend | 当请求结束(包括请求成功和请求失败)时触发 |
onabort | 当调用xhr.abort() 后触发 |
ontimeout | xhr.timeout 不等于0,由请求开始即onloadstart 开始算起,当到达xhr.timeout 所设置时间请求还未结束即onloadend ,则触发此事件。 |
onerror | 在请求过程中,若发生Network error 则会触发此事件(若发生Network error 时,上传还没有结束,则会先触发xhr.upload.onerror ,再触发xhr.onerror ;若发生Network error 时,上传已经结束,则只会触发xhr.onerror )。注意,只有发生了网络层级别的异常才会触发此事件,对于应用层级别的异常,如响应返回的xhr.statusCode 是4xx 时,并不属于Network error ,所以不会触发onerror 事件,而是会触发onload 事件。 |
在哪个xhr
事件中注册成功回调?
从上面介绍的事件中,可以知道若xhr
请求成功,就会触发xhr.onreadystatechange
和xhr.onload
两个事件。 那么我们到底要将成功回调注册在哪个事件中呢?我倾向于 xhr.onload
事件,因为xhr.onreadystatechange
是每次xhr.readyState
变化时都会触发,而不是xhr.readyState=4
时才触发。
xhr.onload = function () {
//如果请求成功
if(xhr.status == 200){
//do successCallback
}
}
上面的示例代码是很常见的写法:先判断http
状态码是否是200
,如果是,则认为请求是成功的,接着执行成功回调。这样的判断是有坑儿的,比如当返回的http
状态码不是200
,而是201
时,请求虽然也是成功的,但并没有执行成功回调逻辑。所以更靠谱的判断方法应该是:当http
状态码为2xx
或304
时才认为成功。
xhr.onload = function () {
//如果请求成功
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
//do successCallback
}
}
- 使用new XMLHttpRequest(),例子:
var xhr = new XMLHttpRequest()
- 目前所有的主流浏览器都内建了 XMLHttpRequest 对象,所以我们可以使用new XMLHttpRequest()的方法来创建,但是在IE5和IE6上只能使用 ActiveXObject()构造函数来创建。 例子:
var xrh = new ActiveXObject("Microsoft.XMLHTTP");
- 兼容低版本IE的写法:
<script type="text/javascript">
function getXMLHttpRequest(){
var xhr = null;
try{
xhr = new XMLHttpRequest();
}
catch(microsoft){
try{
xhr = new ActiveXObject("Msxml2.XMLHTTP");
}
catch(othermicrosoft){
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
}
return xhr
}
</script>
- XMLHttpRequest对象的两个方法:
- .open(method,url,async)**
.open()方法用于设置向服务器请求的参数,它有三个参数:- method:请求的类型,GET 或 POST。
- url:文件在服务器上的位置。
- async:true(异步)或 false(同步)。
使用GET还是POST
- get方式比post方式简单速度更快,但是向服务器传送的数据不能大于2k,向服务器提交的数据会显示在浏览器的url地址上,安全性较差,做数据查询时,建议用Get方式
- post方式传送数据量大,安全性高一般用于以下几种情况:
1.无法使用缓存文件(更新服务器上的文件或数据库)
2.向服务器发送大量数据(POST 没有数据量限制)
3.发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠
4.在做数据添加、修改或删除时,建议用Post方式
URL是相对于当前页面的路径,也可以使用绝对路径,该文件可以是任何类型的文件,比如 .txt 和 .xml,或者服务器脚本文件,比如 .asp 和 .php,只能向同一个域中使用相同协议和端口的URL发送请求,否则会因为安全原因报错。
异步和同步
- 异步
浏览器将请求发送后,继续干其他的事情,也就是说用户可以继续操作页面的其他地方,不受影响,等数据来了浏览器再去处理数据。
同步
浏览器将请求发送后,整个页面就不能进行其他操作,必须等浏览器处理完数据后页面才能进行操作。个人理解就是:页面上有两个按钮,第一个按钮点击后过3秒会出现“你好”,第二个按钮点击后过5秒会出现“欢迎”,如果是在异步的情况下,点击完第一个按钮后,在“你好”还没出现的这三秒时间内,你还可以点击第二个按钮或者做其他的操作,如果是同步,你点击完第一个按钮后,在“你好”还没出现的这三秒时间无法点击第二个按钮,必须等“你好”出现后才能做其他的操作。
- .send(string)**
.send()方法用于将设置好参数的请求发送到服务器,它的参数string仅用于post请求。
向服务器发送请求分两种,一种是不带数据的发送,一种是带数据的发送
- 不带数据的发送
- get方式
var xhr = XMLHttprequest();
xhr.open('GET','xxx.php',true);
xhr.send();
- post方式
var xhr = XMLHttprequest();
xhr.open('POST','xxx.php',true);
xhr.send();
- 带数据的发送
- get方式
使用get方式带数据的请求发送,需要做的就是将要发送的数据变成url地址添加到.open()方法的参数中。
- url的拼接方式:向服务器发送的地址+?数据名=+数据值+&数据名=+数据值,例子:
<body>
<input type="text" name="username">
<input type="password" name="password">
<script type="text/javascript">
var username = document.getElementsByName('username')[0].value;
var password = document.getElementsByName('password')[0].value;
var url = "xxx.php"+"?username="+username+"&password="+password;
var xhr = new XMLHttpRequest();
xhr.open("GET",url,true);
xhr.send();
</script>
</body>
- post方式
前面说过.send(string)方法中的参数string仅用于post请求。就是指的这种情况,它的参数string代表post方式向服务器发送的数据。用post方式向服务器发送数据,还需要使用 setRequestHeader() 来添加 HTTP Header信息。
- HTTP Header信息
每个HTTP请求都会带有Header信息, 告诉服务器客户端要下载什么信息以及相关的参数。
- setRequestHeader( header, value)
使用setRequestHeader方法设置自定义的请求Header信息,这个方法接受两个参数:
1.头部字段的名称(header)
2.头部字段的值(value)
setRequestHeader方法必须在 调用open方法之后, 调用send方法之前调用才能成功发送成功
例子:
var xhr = new XMLHttpRequest();
xhr.open("POST","xxx.php",true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send("name=Alex&age=16");
更多的HTTP Header信息还可以参考:
HTTP协议之HTTP 头
XMLHTTP中setRequestHeader参数问题
理解HTTP之Content-Type
- XMLHttpRequest对象的五个属性:
- responseText
将响应信息作为字符串返回。 - responseXML
将响应信息格式化为Xml Document对象并返回 - status
由服务器返回的 HTTP 状态代码- 200 请求成功
- 404 服务器无法找到被请求的页面。
更多 HTTP 状态代码
- statusText
这个属性返回的是用名称指定了请求的 HTTP 的状态代码,比如:当status的值为200时,它的值为"OK", 当status的值为404的时候它是 "Not Found"。 - readyState
HTTP 请求的状态。屏幕快照 2016-12-08 下午9.26.43.png
- responseText
3. onreadystatechange 事件
只要XMLHttpRequest.readyState属性发生变化,就会触发readystatechange事件。根据前面介绍的XMLHttpRequest对象的status属性和readyState属性我们可以给XMLHttpRequest对象绑定事件监听,当status值为200且readyState值为4的时候,就表示已经从服务器获取到请求的数据了,例子:
<body>
<input type="text" name="username">
<input type="password" name="password">
<input type="submit">
<script type="text/javascript">
var btn = document.getElementsByTagName('input')[2];//获取<input type="submit">元素节点
btn.addEventListener('click',function(){//给btn绑定点击事件监听器
var xhr = new XMLHttpRequest();//创建XMLHttpRequest对象
xhr.onreadystatechange = function(){//给xhr绑定监听器,当请求成功时需要执行的函数。
if(xhr.status == 200 && xhr.readyState == 4){
console.log(xhr.responseText);//当xhr的status 属性的值为4且readyState属性的值为200,在控制台输出从服务器获取到的数据。
}
xhr.open("GET",xxx.php,true);//设置请求参数
xhr.send();//发送请求。
}
},false)
</script>
</body>
4. 最后总结下使用AJAX发送一个请求的步骤:
- 创建一个XMLHttpRequest对象
- 给这个XMLHttpRequest对象绑定一个监听器,当请求成功后,执行我们想要执行的操作。
- 设置请求的参数,包括get和post方式,请求的url地址,异步还是同步。
- 发送请求,如果是post方式,它还有个string参数。
作者:饥人谷_妖葫芦
链接:https://www.jianshu.com/p/a37cd239db4e
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。