脚本化http
ajax
在ajax出现以前,页面的只能通过表单提交数据,服务器接受请求拼接html并返回。浏览器接收到html,渲染新的内容。这种交互的方式缺陷显而易见。就是任何的和服务器的交互都需要刷新页面。用户的体验非常差。ajax的出现解决了这个问题。可以实现将网页应用的增量迅速的呈现给用户,而不需要重载页面。 ajax通过浏览器的XMLHttpRequest来实现,X代表XML。但是由于JSON更加的轻量而且作为JavaScript的一部分,因此JSON的使用比XML更加的普遍。
原生ajax的用法
下面时一个XMLHttpRequest实现一个get请求的伪代码。
function get(url, callback) {
var request = new XMLHttpRequest()
request.send('get', url)
request.onreadystatechange = function() {
if (request.readyState === 4 && request.status === 200) {
var type = request.getResponseHeader('COnten-Type')
if (type.indexOf('xml') !== -1 && request.responseXML) {
callback(request.responseXML) //Document对象相应
} else if (type === 'application/json') {
callback(JSON.parse(request.responseText)) //JSON响应
} else {
callback(request.responseText) //字符串响应
}
}
}
request.send(null)
}
复制代码
XMLHttpRequest对象常用的函数、属性和事件
MLHttpRequest对象常用的函数
函数 | 用法 | 解释 |
---|---|---|
open | xhr.open(method,url,async) | method为请求方式 url:请求地址 aysnc布尔值,代表是否异步请求。默认为true(异步) |
send | xhr.send(data) | 当请求方式为get时,所有参数会拼接在url中,send(null) 请求方式为post时,数据会在请求体中,即send(data) |
abort | xhr.abort() | 用来终止一个ajax请求,调用此方法后readyState将被设置为0,终结请求。 |
setRequestHeader | xhr.setRequestHeader(header,value) | 用来这是HTTP的请求头,必须在open()和send()之间调用 |
getResponseHeader | xhr.getResponseHeader(header) | 用来获取http返回头,如果返回头中有多个一样名称,返回的值中会用逗号和空格将值分割成字符串,会自动过滤掉cookie |
getAllResponseHeaders | xhr.getAllResponseHeaders() | 用来获取所有的请求头,同getResponseHeader一样,会自动过滤掉cookie |
overrideMimeType | xhr. overrideMimeType(MIME类型) | XHR2定义了overideMimeType()方法,并且大多数的浏览器已经实现,若果你比浏览器更了解资源的MIME类型,可以在send()之前把类型传递给overideMimeAType(),这将使XMLHttpRequest忽略"Content-Type"头而使用指定的类型 |
XMLHttpRequest对象常用的属性
属性 | 解释 |
---|---|
readyState | 0代表open()尚未调用,1代表open()已经被调用,2代表接受到头信息 ,3代表接收到响应主体,4代表响应完成。每次的改变会触发readstatechange事件。 |
status | http的请求状态码 |
statusText | 只读属性,状态对应的文本信息 |
responseType | 响应的数据类型,允许我们手动设置。默认text类型(实际上是 DOMString)。 arraybuffer:response 是一个包含二进制数据的 JavaScriptArrayBuffer blob:response是一个包含二进制数据的 Blob 对象 document:response 是一个 HTMLDocument或 XMLXMLDocument,这取决于接收到的数据的 MIME 类型。 json:response是包含在 DOMString对象中的文本。 |
response | 响应的正文,返回的类型由responseType来决定 |
timeout | 超时时间,默认0,没有超时。单位毫秒 |
responseText | 包含对文本的请求的响应,如果请求不成功或尚未发送,则返回null。如果 XMLHttpRequest.responseType 的值不是 text 或者空字符串,届时访问 XMLHttpRequest.responseType 将抛出 InvalidStateError 异常。 |
withCredentials | cookie的设置,默认为true,携带cookie,跨域时,默认为false,不携带。 |
upload | xhr2规范,返回一个XMLHttpRequestUpload对象,用来表示上传的进度。可以绑定的事件: onloadstart获取开始,onprogress数据传输进行中。onabort获取操作终止。onerror失败 onload获取成功 ontimeout获取操作在用户规定的时间内未完成 onloadend获取完成(不论成功与否) |
post请求
POST请求包含一个请求体,默认情况下,表单数据是通过POST发送服务器。将编码的数据表单数据作为请求主体。表单的编码相对简单。使用十六进制转义码替换特殊字符
a=1&b=2&c=3
复制代码
表单的编码格式有一个正式的MIME类型: 传递此种序列化的数据时,必须使用下面的这种'Content-type'
application/x-www-form-urlencoded
复制代码
用于post请求的编码对象:
function encodeFormData(data){
if(!data){
return ''
}
var pairs = []
for(var name in data){
if(!data.hasOwnProperty(name)){
continue
}
if(typeof data[name]==='function'){
continue
}
var value = data[name].toString()
name = encode(name)
value = encode(value)
pairs.push(name + '=' + value)
}
return pairs.join('&')
}
function encode(val) {
return encodeURIComponent(val).
replace(/%40/gi, '@').
replace(/%3A/gi, ':').
replace(/%24/g, '$').
replace(/%2C/gi, ',').
replace(/%20/g, '+').
replace(/%5B/gi, '[').
replace(/%5D/gi, ']');
}
function postData(url, data, callback) {
var request = new XMLHttpRequest()
request.open('POST', url)
request.onreadystatechange = function() {
if (request.readyState === 4 && callback) {
callback(request)
}
}
request.setRequestHeader('Content-Type', 'application/x-www/urlencoded')
request.send(encodeFormData(data))
}
复制代码
JSON编码的请求:
function postJSON(url, data, callback) {
var request = new XMLHttpRequest()
request.open('POST', url)
request.onreadystatechange = function() {
if (request.readyState === 4 && callback) {
callback(request)
}
}
request.setRequestHeader('Content-Type', 'application/json')
request.send(JSON.stringify(data))
}
复制代码
post文件上传 xhr2规范中允许send()方法来接受一个file对象来实现文件的上传,同时
//查找有data-uploadto属性的全部input type=file元素
//并这册onchange事件处理程序
//这样任何选择的文件都会自动通过post方法发送到指定的uploadto的url
//忽略服务器的响应
(function() {
var elts = document.getElementsByTagName('input')
for (var i = 0; i < elts.length; i++) {
var input = elts[i]
if(input.type!=='file') continue;
var url = input.getAttribute('data-uploadto') //获取文件上传的url
if(!url) continue;
input.addEventListener('change',function(){
var file = this.files[0] //假设单个文件的上传
if(!file) return;
var xhr = new XMLHttpRequest();
xhr.open('POST',url)
xhr.send(file)
},false)
}
}())
复制代码
multipart/form-data请求 当HTML表单同时包含文件上传元素和其他元素时,浏览器不能使用普通的表单编码而必须使用multipart/form-data的特殊Content-Type来用POST方法提交表单。这种编码包括使用长"边界"字符串把请求主体分离成多个部分。XHR2 定义了新的FormData的API,它容易实现多部分请求主体。
function postFormData(url, data, callback) {
if (typeof FormData === 'undefined') {
throw new Error('FromData is not implemented')
}
var request = new XMLHttpRequest()
request.open('POST', url)
request.onreadystatechange = function() {
if (request.readyState === 4 && callback) {
callback(request)
}
}
var formdata = new FormData()
for (var name in data) {
if (!data.hasOwnProperty(name)) continue; //如果时继承来的属性,跳过
var value = data[name]
if (typeof value === 'function') continue;
formdata.append(name, data[name]) //没个请求变成主体的一部分
}
// 在multipart/form-data请求主体中发送名。值对
//每对都是请求的一个部分
request.send(formdata)
}
复制代码
get和post的区别(面试常问)
w3cschools上的标准答案
- GET请求在浏览器的回退时时无害的,而POST会再次的提交请求
- GET产生的URL地址可以被Bookmark,而POST不会
- GET请求会被浏览器主动cache,而POST不会,除非手动设置
- GET请求只能通过url编码,而POST支持多种编码方式
- GET请求参数会被完整的保留在浏览器的历史记录中,而POST请求的参数是不会被保留的
- GET请求在URL中传送的参数是有长度限制的(大多数浏览器限制2k,但是大多数服务器最多处理64k的url),POST请求的没有
- 对参数的数据类型GET值接受ASCII字符,而POST没有限制
- POST请求更安全,因为GET请求的参数直接暴露在URL中,所以不能传递敏感信息
- GET参数通过URL传递,POST放在Requestbody中
到这里已经差不多了,但是我要说的是其实GET和POST本质上是没有区别的!
GET和POST是HTTP协议中的两种发送请求方式,而HTTP是基于TCP/IP的关于数据如何在万维网中通信的协议。也就是说GET/POST都是TCP连接,所以本质上来说GET和POST请求能做的事情是一样的。
GET可以加上requestbody,同样POST也可以加上url参数,技术上完全是行的通的。但是对于服务器来说,不同的服务器处理方式不同,有些服务器会帮你获取GET中的requestbody,有些服务器则会直接忽略。因此虽然可以实现,但是不保证一定会被接收。
最后GET和POST还有一个重大的区别,就是GET只会产生一个TCP数据包,而POST产生两个TCP数据包。
对于GET请求方式,浏览器会把http header和一块发送出去,而对于POST请求,浏览器会发送header,服务器响应100 continue,浏览器再发送data,服务器响应返回数据。因此POST请求消耗的事件更多一点,看起来GET比POST更高效。实际上环境好的情况下,发送一次TCP数据包和发送两次数据包消耗的时间差是可以忽略的。但是在网络环境差的情况下,两次TCP在验证数据包的完整性上,是有非常大的优点的。同时并不是所有的浏览器POST都会发送两次数据包,FireFox就只发送一次。