XMLHttpRequest Level 2 標(biāo)準(zhǔn)
在jq中的ajax只是對(duì)于XMLHttpRequest的封裝,
后來(lái)衍生出了一個(gè)fetch,其兼容性,
目前是一個(gè)實(shí)驗(yàn)性的階段。當(dāng)然也有其的polyfill存在。

1.XMLHttpRequest的基本用法
XMLHttpRequest包含prototype屬性,所以是個(gè)函數(shù)不是一個(gè)對(duì)象。
var xhr = new XMLHttpRequest(); //創(chuàng)建一個(gè)XMLHttpRequest對(duì)象
console.log(xhr.readyState); //0
xhr.open('GET', 'test.action',true); //打開(kāi)并且為異步
xhr.timeout=2000; //設(shè)置超時(shí)時(shí)間為2000毫秒,默認(rèn)0 沒(méi)有超時(shí)
xhr.responseType='text' //默認(rèn)是空字符串等同于`text`,還有`arraybuffer`, `blob`, `document`, `json`類(lèi)型,
//老版本采用`overrideMimeType`方法
console.log(xhr.readyState); //1
xhr.setRequestHeader('name','diandi') //設(shè)置請(qǐng)求頭,必須是打開(kāi)狀態(tài)的時(shí)候才能設(shè)置
xhr.onreadystatechange= function(){ //每次readyState改變都會(huì)進(jìn)
console.log(xhr.response); //響應(yīng)的對(duì)象
console.log(xhr.responseText); //返回對(duì)應(yīng) xhr.responseType的類(lèi)型的數(shù)據(jù)
console.log(xhr.responseXML); //返回的XML格式的數(shù)據(jù)
console.log(xhr.status) //返回的狀態(tài)碼
};
xhr.send('test'); //發(fā)送數(shù)據(jù)
1.1 四種狀態(tài)xhr.readyState
| 狀態(tài) | 狀態(tài)值 | 描述 |
|---|---|---|
| UNSENT | 0 | 未使用剛初始化 |
| OPENED | 1 | 打開(kāi)狀態(tài)可以設(shè)置RequestHeader
|
| HEADERS_RECEIVED | 2 | 接收到響應(yīng)頭 |
| LOADING | 3 | 接收響應(yīng)內(nèi)容中 |
| DONE | 4 | 接收結(jié)束 |
1.2 獲取上傳和下載的進(jìn)度條
xhr.onprogress = function(evt){}; //下載的事件
xhr.upload.onprogress = function(evt){}; //上傳的事件
evt的參數(shù)說(shuō)明
參數(shù) | 描述
---:| ---
total | 傳輸?shù)目傋止?jié)
loaded | 完成傳輸?shù)淖止?jié)
lengthComputable | 如果長(zhǎng)度不為0,則設(shè)置為true,并且設(shè)置total,當(dāng)數(shù)據(jù)響應(yīng)的時(shí)候Content-Encoding:gzip的時(shí)候不能獲取內(nèi)容長(zhǎng)度
相關(guān)事件
類(lèi)型 | 描述 | 次數(shù) | 條件
---:| --- | ---| ---
onloadstart |Progress開(kāi)始的時(shí)候 | 一次 | 首先
onprogress |Progress中 | 一次或更多。 |loadstart觸發(fā)以后
onerror |Progress失敗 | 沒(méi)有或者一次 | 最后一個(gè)progress觸發(fā)以后
onabort |Progress被終止 | 沒(méi)有或者一次 | 最后一個(gè)progress觸發(fā)以后
ontimeout | 超時(shí)Progress被終止 | 沒(méi)有或者一次 | 最后一個(gè)progress觸發(fā)以后
onload |progress成功 | 沒(méi)有或者一次 | 最后一個(gè)progress觸發(fā)以后
onloadend |progress結(jié)束 | 一次 |error或abort或timeout或load觸發(fā)以后
1.3 send方法支持的類(lèi)型
function send();
function send(ArrayBufferView data);
function send(Blob data);
function send(Document data);
function send(DOMString? data);
function send(FormData data);
參考資料
CORS
瀏覽器都會(huì)包含著同源的安全策略。同源政策的目的,是為了保證用戶(hù)信息的安全,防止惡意的網(wǎng)站竊取數(shù)據(jù)。
不同的端口、不同的協(xié)議、不同的域名都是不同源。CORS需要瀏覽器和服務(wù)器同時(shí)支持,但是客戶(hù)端不需要改動(dòng)什么,
目前,所有瀏覽器都支持該功能,IE瀏覽器不能低于IE10。
并且在chrome下跨越請(qǐng)求只支持http, data, chrome, chrome-extension, https, chrome-extension-resource協(xié)議。

1. 簡(jiǎn)單請(qǐng)求,不需要請(qǐng)求2次,只使用GET、POST進(jìn)行的請(qǐng)求,請(qǐng)求沒(méi)有自定義的請(qǐng)求頭。
1.1 客戶(hù)端代碼
var xhr=new XMLHttpRequest();
xhr.open('get','http://localhost:3000');
//xhr.open('post','http://localhost:3000');
xhr.send();
1.2 服務(wù)端代碼
var koa = require('koa');
var app = koa();
app.use(function*() {
this.set('Access-Control-Allow-Origin', '*');
this.body = this.method == 'POST' ? 'is Post' : 'is Get';
});
app.listen(3000);
Access-Control-Allow-Origin為設(shè)置允許請(qǐng)求的來(lái)源地址,*代表全部
2. 需要先OPTIONS請(qǐng)求來(lái)檢驗(yàn)是否允許請(qǐng)求,然后再次請(qǐng)求,可以設(shè)置各種頭
2.1 客戶(hù)端代碼
var xhr=new XMLHttpRequest();
xhr.open('get','http://localhost:3000');
//xhr.open('post','http://localhost:3000');
xhr.setRequestHeader('Foo','http://localhost:3000');
xhr.send();
2.2 服務(wù)端代碼
var koa = require('koa');
var app = koa();
app.use(function*() {
this.set('Access-Control-Allow-Origin', '*');
this.set('Access-Control-Allow-Headers', 'foo');
this.body = this.method == 'POST' ? 'is Post' : 'is Get';
});
app.listen(3000);
Access-Control-Allow-Headers大小中定義的請(qǐng)求頭的大小寫(xiě)不敏感,用逗號(hào)隔開(kāi)
3. 提交cookie信息,如果不改變RequestHeader,也只請(qǐng)求一次
3.1 客戶(hù)端代碼
var xhr=new XMLHttpRequest();
xhr.open('get','http://localhost:3000');
//xhr.open('post','http://localhost:3000');
xhr.withCredentials=true;
xhr.send();
3.2 服務(wù)端代碼
var koa = require('koa');
var app = koa();
app.use(function*() {
this.set('Access-Control-Allow-Origin', 'http://test.in66.com:8080');
this.set('Access-Control-Allow-Credentials', true);
this.body = this.method == 'POST' ? 'is Post' : 'is Get';
});
app.listen(3000);
Access-Control-Allow-Credentials必須為true且Access-Control-Allow-Origin必須是指定的來(lái)源地址,
其中的Cookie只會(huì)提交http://localhost:3000下的Cookie信息
4. 其他的服務(wù)器返回頭
| 字段 | 說(shuō)明 |
|---|---|
| Access-Control-Expose-Headers | 設(shè)置相應(yīng)返回的時(shí)候可以讀取的頭,不設(shè)置的時(shí)候能讀取Content-Type
|
| Access-Control-Allow-Methods | 是逗號(hào)分隔的一個(gè)字符串,表明服務(wù)器支持的所有跨域請(qǐng)求的方法 |
| Access-Control-Max-Age |
OPTIONS請(qǐng)求的有效期,以秒為單位 |
FormData
利用FormData可以完全模擬實(shí)現(xiàn)提交表單,也彌補(bǔ)了以前上傳文件只能利用target是一個(gè)iframe的方法
1.基本用法
var oform = new FormData();
oform.append("name", "diandi");
oform.append("age", 10);
oform.append("file", input.files[0]);//上傳控件的文件
...... //構(gòu)建xhr
xhr.send(oform);
2.直接通過(guò)一個(gè)表單元素
var ele = document.getElementById("testform");
oform = new FormData(ele);
...... //構(gòu)建xhr
xhr.send(oform);
3.文件分塊上傳
var oform = new FormData();
var fsize=input.files[0].size; //獲取文件的大小
oform.append("file", input.files[0].slice(0,10)); //上傳文件前面10長(zhǎng)度的二進(jìn)制
...... //構(gòu)建xhr
xhr.send(oform);
input.files[0].slice(0,10)分割后的為Blob,File基于Blob,繼承了Blob的功能.
4.文件上傳進(jìn)度
var formData = new FormData();
formData.append('key', key)
formData.append('token', tokens)
formData.append('file', files);
$.ajax({
url: uploadQiNiuurl,
type: 'POST',
data: formData,
contentType: false,
processData: false,
beforeSend: function(XMLHttpRequest) {
XMLHttpRequest.upload.addEventListener("progress", function(evt) {
if (evt.lengthComputable) {
filesPercentArr[index] = {
loaded: evt.loaded,
total: evt.total,
}
dtd.notify(filesPercentArr);
}
}, false);
}
}).done(function(res) {
}).fail(functio() {}))