接收响应
一个完整的HTTP响应由状态码、响应头集合和响应主体组成。在收到响应后,这些都可以通过XHR对象的属性和方法使用,主要有以下4个属性
responseText: 作为响应主体被返回的文本(文本形式)
responseXML: 如果响应的内容类型是'text/xml'或'application/xml',这个属性中将保存着响应数据的XML DOM文档(document形式)
status: HTTP状态码(数字形式)
statusText: HTTP状态说明(文本形式)
在接收到响应后,第一步是检查status属性,以确定响应已经成功返回。一般来说,可以将HTTP状态码为200作为成功的标志。此时,responseText属性的内容已经就绪,而且在内容类型正确的情况下,responseXML也可以访问了。此外,状态码为304表示请求的资源并没有被修改,可以直接使用浏览器中缓存的版本;当然,也意味着响应是有效的。
无论内容类型是什么,响应主体的内容都会保存到responseText属性中,而对于非XML数据而言,responseXML属性的值将为null
if((xhr.status >=200 && xhr.status < 300) || xhr.status == 304){
alert(xhr.responseText);
}else{
alert('request was unsuccessful:' + xhr.status);
}
GET
let xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET', 'url', true);
xmlhttp.send();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
console.log(JSON.parse(xmlhttp.response));
let response = JSON.parse(xmlhttp.response);
if (response.status == 200) {
alert("创建成功");
} else {
alert("创建失败");
}
} else if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
alert("网络错误,请稍后重试");
}
}
POST
let data = {
guestRoomID : form.room_id.value,
position : form.room_position.value,
type : form.room_type.value,
power: 1
}
let xmlhttp = new XMLHttpRequest();
xmlhttp.open('POST', 'url', true);
xmlhttp.setRequestHeader("Content-type", "application/json");
xmlhttp.send(JSON.stringify(data));
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
console.log(JSON.parse(xmlhttp.response));
let response = JSON.parse(xmlhttp.response);
if (response.status == 200) {
alert("创建成功");
} else {
alert("创建失败");
}
} else if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
alert("网络错误,请稍后重试");
}
}
//无data
let xmlhttp = new XMLHttpRequest();
xmlhttp.open('POST', url, true);
xmlhttp.setRequestHeader('Content-type', 'application/json');
xmlhttp.send();
//无data
let xmlhttp = new XMLHttpRequest();
xmlhttp.open('POST', url, true);
xmlhttp.setRequestHeader('Content-type', 'application/json');
xmlhttp.send(JSON.stringify());
PUT
let xmlhttp = new XMLHttpRequest();
xmlhttp.open('PUT', 'url', true);
xmlhttp.setRequestHeader('Content-type','application/json');
xmlhttp.send(JSON.stringify(data));
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
console.log(JSON.parse(xmlhttp.response));
let response = JSON.parse(xmlhttp.response);
if (response.status == 200) {
alert("创建成功");
} else {
alert("创建失败");
}
} else if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
alert("网络错误,请稍后重试");
}
}
DELETE
let xmlhttp = new XMLHttpRequest();
xmlhttp.open("DELETE", url, true);
xmlhttp.send();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
console.log(JSON.parse(xmlhttp.response));
let response = JSON.parse(xmlhttp.response);
if (response.status == 200) {
alert("创建成功");
} else {
alert("创建失败");
}
} else if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
alert("网络错误,请稍后重试");
}
}
js的引用方法
- 报错Cannot use import statement outside a module的解决方法
//html
<script type="module" src="../js/index.js"></script>
//index.js
import data from './config.js'
let totalUrl = data.globalData.totalUrl;
console.log(totalUrl);
//config.js
let globalData = {
totalUrl : 'http://wktds9.natappfree.cc'
}
export default {
globalData
}
使用liveServer插件开始为服务器,在html右键open with live Server
JS获取浏览器之间参数
/**
*传入截取字符的属性名,返回截取的属性值
*/
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]); return null;
}
//缺点是不支持浏览器中有中文
JS获取url参数
function parseUrl(url) {
// 找到url中的第一个?号
var parse = url.substring(url.indexOf("?") + 1),
params = parse.split("&"),
len = params.length,
item = [],
param = {};
for (var i = 0; i < len; i++) {
item = params[i].split("=");
param[item[0]] = item[1];
}
return param;
}
// demo:
parseUrl("www.haorooms.com/js?name=haorooms&age=21&page=2")
// 结果
{name: "haorooms", age: "21", page: "2"}
URL参数拼接
/**
* @description 将传入的url参数对象解析组装成字符串做为queryString中的一部分
* @param {Object} params 参数的数组
* @param {string} cgi 路径
* @return {String} queryString部分字符串
* @example : param1=value1¶m2=value2¶m3=value3......
*/
function convert_params(params, cgi){
var paramsArray = [];
for (var name in params) {
if (paramsArray.length == 0) {
cgi && cgi.indexOf('?') != -1 ? paramsArray.push("&") : paramsArray.push("?");
}
else {
paramsArray.push("&");
}
paramsArray.push(name);
paramsArray.push("=");
paramsArray.push(params[name]);
}
return paramsArray.join("");
}
console.log(convert_params({"param": "value1", "param2": "value2"}, "/post/"));
// ?param=value1¶m2=value2
console.log(convert_params({"param": "value1", "param2": "value2"}, "/post/?page=1"));
// ¶m=value1¶m2=value2
获取URL后面锚点ID
http://www.haorooms.com/#haorooms
要获取后面的#haorooms。
有的同学可能还要获取浏览器地址,然后用indexOf获取到#的位置,然后在拿到#haorooms,或者其他比较繁琐的办法,今天讲一个最简单有效的方法,用js自带方法就可以获取,一句代码搞定!
var thisId = window.location.hash;
就可以直接获取到#haorooms
我们可以进行如下判断:
var thisId = window.location.hash;
if(thisId != "" && thisId != undefined){
}
浏览器编码
“只有字母和数字[0-9a-zA-Z]、一些特殊符号“$-_.+!*'(),”[不包括双引号]、以及某些保留字,才可以不经过编码直接用于URL。”
无论网页的原始编码是什么,一旦被Javascript编码,就都变为unicode字符。
由HTML源码中字符集的设定决定。
<meta http-equiv="Content-Type" content="text/html;charset=xxxx">
如果上面这一行最后的charset是UTF-8或是GB2312,URL就以对应的编码。GET和POST方法的编码,用的是网页的编码。
escape()不对“+”编码。但是我们知道,网页在提交表单的时候,如果有空格,则会被转化为+字符。服务器处理数据的时候,会把+号处理成空格。
方法一:escape()
escape()来编码字符串;unescape()来解码字符串;
方法二:encodeURIComponent()
encodeURIComponent()编码,decodeURIComponent()进行解码;
encodeURIComponent() 函数可把字符串作为 URI 组件进行编码。
该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ’ ( ) 。
其他字符(比如 :;/?😡&=+$,# 这些用于分隔 URI 组件的标点符号),都是由一个或多个十六进制的转义序列替换的。
var test1="http://www.haorooms.com/My first/";
var nn=encodeURI(test1);
var now=decodeURI(test1);
http://www.haorooms.com/My%20first/
http://www.haorooms.com/My first/
var test1="http://www.haorooms.com/My first/";
var bb=encodeURIComponent(test1);
var nnow=decodeURIComponent(bb);
http%3A%2F%2Fwww.haorooms.com%2FMy%20first%2F
http://www.haorooms.com/My first/
GET请求
get请求的查询字符串都必须使用encodeURIComponent()编码
function addURLParam(url, name, value) {
url += (url.indexOf("?") == -1 ? "?" : "&");
url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
return url;
}
HTTP请求的时限
有时,ajax操作很耗时,而且无法预知要花多少时间。如果网速很慢,用户可能要等很久。
新版本的XMLHttpRequest对象,增加了timeout属性,可以设置HTTP请求的时限。
xhr.timeout = 3000;
上面的语句,将最长等待时间设为3000毫秒。过了这个时限,就自动停止HTTP请求。与之配套的还有一个timeout事件,用来指定回调函数。
xhr.ontimeout = function(event){
alert('请求超时!');
}
不过在超时后访问status属性则会发生错误,可以把检查status的语句放到try/catch中。
目前,Opera、Firefox和IE 10支持该属性,IE 8和IE 9的这个属性属于XDomainRequest对象,而Chrome和Safari还不支持。
xhr.open('post','test.php',true);
xhr.ontimeout = function(){
console.log('The request timed out.');
}
xhr.timeout = 1000;
xhr.send();
FormData对象
ajax操作往往用来传递表单数据。为了方便表单处理,HTML 5新增了一个FormData对象,可以模拟表单。
首先,新建一个FormData对象。
var formData = new FormData();
然后,为它添加表单项。
formData.append('username', '张三');
formData.append('id', 123456);
最后,直接传送这个FormData对象。这与提交网页表单的效果,完全一样。
xhr.send(formData);
FormData对象也可以用来获取网页表单的值。
var form = document.getElementById('myform');
var formData = new FormData(form);
formData.append('secret', '123456'); // 添加一个表单项
xhr.open('POST', form.action);
xhr.send(formData);
上传文件
新版XMLHttpRequest对象,不仅可以发送文本信息,还可以上传文件。
假定files是一个"选择文件"的表单元素(input[type=“file”]),我们将它装入FormData对象。
var formData = new FormData();
for (var i = 0; i < files.length;i++) {
formData.append('files[]', files[i]);
}
然后,发送这个FormData对象。
xhr.send(formData);
进度事件的种类
进度事件用来描述资源加载的进度,主要由 AJAX 请求、<img>
、<audio>
、<video>
、<style>
、<link>
等外部资源的加载触发,继承了ProgressEvent
接口。它主要包含以下几种事件。
- abort:外部资源中止加载时(比如用户取消)触发。如果发生错误导致中止,不会触发该事件。
- error:由于错误导致外部资源无法加载时触发。
- load:外部资源加载成功时触发。
- loadstart:外部资源开始加载时触发。
- loadend:外部资源停止加载时触发,发生顺序排在error、abort、load等事件的后面。
- progress:外部资源加载过程中不断触发。
- timeout:加载超时时触发。
MIME类型
媒体类型(通常称为 Multipurpose Internet Mail Extensions 或 MIME 类型 / 多功能网际邮件扩充协议)是一种标准,用来表示文档、文件或字节流的性质和格式。
网络中媒体一种格式, 在http协议中, 不认识后缀名, 只认识MIME类型, 只要你设置对MIME类型,浏览器会用指定的引擎解析对应的数据。在HTTP中,MIME类型被定义在Http响应的响应头 的Content-Type字段中。(network->head)
MIME意为多目Internet邮件扩展,它设计的最初目的是为了在发送电子邮件时附加多媒体数据,让邮件客户程序能根据其类型进行处理。然而当它被HTTP协议支持之后,它的意义就更为显著了。它使得HTTP传输的不仅是普通的文本,而变得丰富多彩。
访问一个网页,获得一个资源后,浏览器通过媒体资源类型MIME Type,媒体资源类型通过http协议,由web服务器告知浏览器,更详细的说,是通过Content-Type来定义的。
例如:Content-Type: text/HTML
通常只有一些在互联网上获得广泛应用的格式才会获得一个 MIME Type,如果是某个客户端自己定义的格式,一般只能以 application/x- 开头。
怎么获得MimeType ?
servletContext.getMimeType(file.getName());
这个方法会根据文件名自动分割出文件的后缀名,并且根据后缀名去tomcat/conf/web.xml中查取的对应关系,并返回。
服务器传到客户端的文件mime类型的详细过程:
Web服务器和浏览器(包括操作系统)中,缺省都设置了标准的和常见的MIME类型,只有对于不常见的 MIME类型,才需要同时设置服务器和客户浏览 器,以进行识别。
由于MIME类型与文档的后缀相关,因此服务器使用文档的后缀来区分不同文件的MIME类型,服务器中必须定义文档后缀 和MIME类型之间的对应关系。而客户程序从服务器上接收数据的时候,它只是从服务器接受数据流,并不了解文档的名字,因此服务器必须使用附加信息来告诉 客户程序数据的MIME类型。服务器在发送真正的数据之前,就要先发送标志数据的MIME类型的信息,这个信息使用Content-type关键字进行定义,例如对于HTML文档,服务器将首先发送以下两行MIME标识信息,这个标识并不是真正的数据文件的一部分。
Content-type: text/html
空行 “ ”
注意,第二行为一个空行,这是必须的,使用这个空行的目的是将MIME信息与真正的数据内容分隔开。