最近在研究egret热更新这一块,遇到了一个坑,特意在这里转载这篇文章供大家参考。
转自:http://nanchao.win/2016/12/19/ajax-status/
对于每个 ajax 请求,onreadystatechange 事件都会触发 5 次,对应 readyState 从 0 到 4 变化。例:值为 4 表示请求已经完成或者传输过程中出现错误。readyState 总共有 5 个状态值,分别为 0 ~ 4,每个值代表了不同的含义:
0 (UNSENT):初始化,XMLHttpRequest 对象还没有完成初始化
1 (OPENED):载入,XMLHttpRequest 对象开始发送请求
2 (HEADERS_RECEIVED):载入完成,XMLHttpRequest 对象的请求发送完成
3 (LOADING):解析,XMLHttpRequest 对象开始读取服务器的响应
4 (DONE):数据传输已完成或传输过程中出现问题(例如无限重定向、跨域等)。
status 表示响应的 HTTP 状态码。在 HTTP1.1 协议下,HTTP 状态码总共可分为 5 大类:
1xx:信息响应类,表示接收到请求并且继续处理
2xx:处理成功响应类,表示动作被成功接收、理解和接受
3xx:重定向响应类,为了完成指定的动作,必须接受进一步处理
4xx:客户端错误,客户请求包含语法错误或者是不能正确执行
5xx:服务端错误,服务器不能正确执行一个正确的请求
一般情况下,对于一个异步的 ajax 请求,如需响应成功后执行某操作,我们会这样写:
function getResource(url){
var xhr;
if (window.XMLHttpRequest){
xhr = new XMLHttpRequest();
} else {
//code for IE5, IE6
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
xhr.onreadystatechange = function (){
if (xhr.readyState == 4 && xhr.status == 200){
//doSomething();
}
};
xhr.open('GET', url, true);
xhr.send(null);
}
即满足 xhr.readyState == 4 && xhr.status == 200,才能表示请求成功!
我们把以上代码稍微改写一下,打印出每次 ajax 请求返回的状态码:
function getStatus(url){
var xhr;
if (window.XMLHttpRequest){
xhr = new XMLHttpRequest();
} else {
//code for IE5, IE6
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
xhr.onreadystatechange = function (){
if (xhr.readyState == 4) {
console.log('status:',xhr.status);
}
};
xhr.open('GET', url, true);
xhr.send(null);
}
实际应用中,会发现存在少量用户打印出的 xhr.status 值为0。这就奇怪了,http 状态码也没有值为 0 的场景,这里的 0 又是怎么来的?
官方文档https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/ 指出:
status 值会由以下几个步骤确定:
1.If the state is UNSENT or OPENED, return 0.
2.If the error flag is set, return 0.
3.Return the HTTP status code.
也就是说,如果 readyState 是 UNSENT(0)或 OPENED(1)状态,status 返回值为 0;如果出现某种网络错误或者请求终止,error flag 就会由 unset 变为 set,status 返回值也为 0;否则,返回 http 状态码。
下面举例说明:
调取跨域资源,status 会返回 0:
getStatus('https://www.baidu.com');
控制台会打印:status: 0,同时报出错误:XMLHttpRequest cannot load https://www.baidu.com/. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://www.nc.com’ is therefore not allowed access.
调取本地文件,status 同样会返回 0:
getStatus('file:///E:/www/www.nc.com/index.html');
控制台会打印:status: 0,同时报出错误:XMLHttpRequest cannot load file:///D:/www/www.nc.com/index.html. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.