XMLHttpRequest Level 2 標(biāo)準(zhǔn)、CORS

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é)束 | 一次 | erroraborttimeoutload觸發(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次,只使用GETPOST進(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必須為trueAccess-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() {}))
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容