什麼是AJAX?async javascript and xml 異步的JS和XMLjavascript
做用:是用來存儲數據的(經過本身擴展的標記名稱清晰地展現出數據結構)ajax之因此稱爲異步的js和xml,主要緣由是:之前最開始使用ajax實現客戶端和服務端數據通訊的時候,傳輸數據的格式通常都是xml格式的數據,咱們把他稱之爲異步的js和xml(如今通常都是基於JSON格式來進行數據傳輸的)html
<?xml version="1.0" encoding="UTF-8"?> <root> <student> <name>海洋</name> <age>10</age> <score> <deutsch>100</deutsch> <IT>100</IT> <english>100</english> </score> </student> </root>
這裏的異步不是說ajax只能基於異步進行請求(雖然建議都是使用異步編程),這裏的異步特指的是 局部刷新
全局刷新:在非徹底先後端分離的項目中,前端開發只須要完成頁面的製做,而且把一些基礎的人機交互效果使用js完成便可,頁面中須要動態呈現內容的部分,都是交給後臺開發工程師作數據綁定和基於服務器進行渲染的(服務器端渲染)前端
【優點】java
- 動態展現的數據在頁面的源代碼中能夠看見,有利於SEO優化推廣(有利於搜索引擎的收錄和抓取)
- 從服務器端獲取的結果已是解析渲染完成的了,不須要客戶端再去解析渲染了,因此頁面加載速度快(前提是服務器端處理的速度夠快,可以處理過來),因此相似於京東,淘寶這些網站,首屏數據通常都是由服務器端渲染的
【弊端】git
- 若是頁面中存在實時更新的數據,每一次想要展現最新的數據,頁面都要從新刷新一次,這樣確定不行,很是耗性能
- 都交給服務器端作數據渲染,服務器端的壓力太大,若是服務器處理不過來,頁面呈現的速度更慢(因此像京東和淘寶這類的網站,除了首屏是服務器端渲染的,其餘屏通常都是客戶端作數據渲染綁定的)
- 這種模式不利於開發,(開發效率低)
局部刷新github
目前市場上大部分項目都是先後端徹底分離的項目(也有非徹底先後端分離的佔少數)面試
先後端徹底分離的項目,頁面中須要動態綁定的數據是交給客戶端完成渲染的ajax
- 向服務器端發送AJAX請求
- 把從服務器端獲取的數據解析處理,拼接成咱們須要展現的HTML字符串
- 把拼接好的字符串替換頁面中的某一部份內容(局部刷新),頁面不須要總體從新加載,局部渲染便可
【優點】編程
- 咱們能夠根據需求,任意修改頁面中的某一部份內容(例如實時刷新),總體頁面不刷新,性能好,體驗好(全部表單驗證,須要實時刷新的等需求都要基於AJAX實現)
- 有利於開發,提升開發效率
1)先後端的徹底分離,後臺不須要考慮前端如何實現,前端也不須要考慮後臺用什麼技術,真正意義上實現了技術的劃分json
2)能夠同時進行開發:項目開發開始,首先制定先後端數據交互的接口文檔(文檔中包含了,調取哪一個接口或者哪些數據等協議規範),後臺把接口先寫好(目前不少公司也須要前端本身拿NODE來模擬這些接口),客戶端按照接口調取便可,後臺再去實現接口功能便可
【弊端】
- 不利於SEO優化:第一次從服務器端獲取的內容不包含須要動態綁定的數據,因此頁面的源代碼中沒有這些內容,不利於SEO收錄,後期經過JS添加到頁面中的內容,並不會寫在頁面的源代碼中(是源代碼不是頁面結構)
- 交由客戶端渲染,首先須要把頁面呈現,而後在經過JS的異步AJAX請求獲取數據,在進行數據綁定,瀏覽器再把動態增長的部分從新渲染,無形中浪費了一些時間,沒有服務器端渲染頁面呈現速度快
// 建立一個AJAX對象 let xhr = new XMLHttpRequest(); // 不兼容IE6及更低版本瀏覽器(IE6:ActiveXObject) // 打開請求地址(能夠理解爲一些基礎配置,可是並無發送請求呢) xhr.open([method],[url],[async],[userName],[passWord]); // 監聽AJAX狀態改變,獲取響應信息(獲取響應頭信息,獲取響應主體信息) xhr.onreadystatechange = ()=>{ if(xhr.readyState === 4 && xhr.status === 200){ let result = xhr.responseText; // 獲取響應主體中的內容 } }; // 發送AJAX請求(括號中傳遞的內容就是請求主體的內容) xhr.send(null);
分析第二步中的細節點
xhr.open([method],[url],[async],[userName],[passWord])
[AJAX請求方式]
GET請求系列(獲取)
- get
- delete:從服務器上刪除某些資源文件
- head:只想獲取服務器返回的響應頭信息(響應主體不須要獲取)
POST請求系列(推送)
- post
- put:向服務器中增長指定的資源文件
無論哪種請求方式,客戶端均可以把信息傳遞給服務器端,服務器端也能夠把信息返回給客戶端,只是GET系列通常以獲取爲主(給的少,拿回來的多),而POST系列通常以推送爲主(給的多,拿回來的少)
1)咱們想要獲取一些動態展現的信息,通常使用GET請求,由於只須要向服務器端發送請求,告訴服務器端咱們想要什麼,服務器端就會把須要的數據返回
2)在實現註冊功能的時候,咱們須要把客戶輸入的信息發送給服務器進行存儲,服務器通常返回成功或失敗等狀態,此時咱們通常都是基於POST請求完成的
GET系列請求和POST系列請求,在項目實戰中存在不少的區別
- GET請求傳遞給服務器的內容通常沒有POST請求傳遞給服務器的內容多
緣由:GET請求傳遞給服務器內容通常都是基於 URL地址問號傳遞參數 來實現的,而POST請求通常都是基於 設置請求主體 來實現的,各個瀏覽器都有URL最大長度的限制(谷歌:8kb,火狐:7kb,IE:2kb),超出長度部分,瀏覽器會自動截取掉,致使傳遞給服務器的數據缺失
理論上POST請求經過請求主體傳遞是沒有大小限制的,真實項目中爲了保證傳輸的速率,咱們也會限制大小(例如:上傳的資料或者圖片咱們會作大小的限制)
- GET請求很容易出現緩存(這個緩存不可控,通常咱們都不須要),而POST不會出現緩存(除非本身作特殊處理)
緣由:GET是經過URL問號傳參傳遞給服務器信息,會出現緩存;而POST是設置請求主體,不會出現緩存。
// 每隔一分鐘從新請求服務器端最新的數據,而後展現在頁面中(頁面中某些數據實時刷新) setTimeout(()=>{ $.ajax({ url: 'getList?lx = news', ... success: result=>{ // 第一次請求數據回來,間隔一分鐘後,瀏覽器又發送一次請求,可是新發送的請求不管是地址仍是傳遞的參數都和第一次如出一轍,瀏覽器頗有可能會把上一次的數據獲取,而不是獲取最新的數據 } }) },600) // 解決方案:在每一次從新請求的時候,在URL的末尾追加一個隨機數,保證每一次請求的地址不徹底一致,就能夠避免是從緩存中讀取的數據 setTimeout(()=>{ $.ajax({ url: 'getList?lx = news&_=' + Math.random(), ... success: result=>{ } }) },600)
- GET請求沒有POST請求安全(POST也並非十分安全,只是相對安全)
緣由:仍是由於GET是URL傳參給服務器
有一種比較簡單的黑客技術:URL劫持,也就是能夠把客戶端傳遞給服務器的數據劫持到,致使信息泄露
URL:請求數據的地址(API地址),在真實項目中,後臺開發工程師會編寫一個API文檔,在API文檔中彙總了獲取哪些數據須要使用哪些地址,咱們按照文檔操做便可ASYNC:異步(SYNC 同步),設置當前AJAX請求是異步的仍是同步的,不寫默認是異步(TRUE),若是設置爲FALSE,則表明當前請求是同步的
用戶名和密碼:這兩個參數通常不用,若是你請求的URL地址所在的服務器設定了訪問權限,則須要咱們提供可通行的用戶名和密碼才能夠(通常服務器都是能夠匿名訪問的)
分析第三步中的細節點
AJAX狀態碼:描述當前AJAX操做狀態的:
xhr.readyState
0:UNSENT未發送,只要建立一個AJAX對象,默認值就是零
1:OPENED 咱們已經執行了xhr.open這個操做
2:HEADERS_RECEIVED 當前AJAX的請求已經發送,而且已經接收到服務器端返回的響應頭信息了
3:LOADING 響應主體的內容正在返回的路上
4:DONE 響應主體內容已經返回到客戶端
HTTP網絡狀態碼:記錄了當前服務器返回信息的狀態 :
xhr.status
200:成功,一個完整的HTTP事務完成(以2開頭的狀態碼通常都是成功)
以3開頭通常也是成功,只不過服務器端作了不少處理
301:Moved Permanently 永久轉移(永久重定向),通常應用於域名遷移
302:Move temporarily 臨時轉移 (臨時重定向,新的HTTP版本中任務307是臨時重定向),通常用於服務器的負載均衡:當前服務器處理不過來,把當前請求臨時交給其餘的服務器處理(通常圖片請求常常出現302,不少公司都有單獨的圖片服務器)
304:Not Modified 從瀏覽器緩存中獲取數據。把一些不常常更新的文件或者內容緩存到瀏覽器中,下一次從緩存中獲取,減輕服務器壓力,也提升頁面加載速度
以4開頭的,通常都是失敗,並且客戶端的問題偏大
400:請求參數錯誤
401:無權限訪問
404:訪問地址不存在
以5開頭的,通常都是失敗,並且服務器端的問題偏大
500:Internal Server Error 未知的服務器錯誤
503:Service Unavailable 服務器超負載
面試題:AJAX中總共支持幾個方法?
let xhr = new XMLHttpRequest(); console.dir(xhr); //【屬性】 // 1.readyState:存儲的是當前AJAX的狀態碼 // response/responseText/responseXML:都是用來接收服務器返回的響應主體中的內容,只是根據服務器返回內容格式的不同,咱們使用不一樣的屬性接收便可 // responseText是最經常使用的,接收的結果是字符串格式的(通常服務器返回的數據都是JSON格式字符串) // responseXML偶爾會用到,若是服務器返回的是XML文檔數據,咱們須要使用這個屬性接收 // status:記錄了服務器端返回的HTTP狀態碼 // statusText:對返回的狀態碼的描述 // timeout:設置當前AJAX請求的超時時間,假設咱們設置時間爲3000ms,從AJAX 請求發送開始,3秒後響應主體內容尚未返回,瀏覽器會把當前AJAX請求任務強制斷開 // 【方法】 // abort():強制中斷AJAX請求 // getAllResponseHeaders():獲取所有的響應頭信息(獲取的結果是一堆字符串文本) // getResponseHeader(key):獲取指定屬性名的響應頭信息,例如:xhr.getResponseHeader('date')獲取響應頭中存儲的服務器的時間 // open():打開一個URL地址 // overrideMimeType():重寫數據的MIME類型 // send():發送AJAX請求(括號中寫的是客戶端基於請求主體把信息傳遞給服務器) // setRequestHeader(key,value):設置請求頭信息(能夠是設置自定義請求頭信息) // [事件] // onabort:當AJAX被中斷請求時觸發這個事件 // onreadystatechange:AJAX狀態發生改變會觸發這個事件 // ontimeout:當AJAX請求超時,會觸發這個事件
例子:
let xhr = new XMLHttpRequest(); xhr.open('get','temp.json?_=' + Math.random(), true); xhr.setRequestHeader('aaa', '123'); // 注意:請求頭部的內容不得出現中文漢字。設置請求頭信息必須在OPEN以後和SEND以前 // 設置超時 xhr.timeout = 10; xhr.ontimeout = ()=>{ console.log('當前請求已經超時'); xhr.abort(); }; xhr.onreadystatechange = ()=>{ let {readyState:state, status} = xhr; if(!/^(2|3)\d{2}$/.test(status)) return; // 在狀態爲2的時候就能夠獲取響應頭信息 if (state === 2){ let headerAll = xhr.getAllResponseHeaders(), serverDate = xhr.getResponseHeader('date'); // 獲取的服務器時間是格林尼治時間(相比北京時間差了8小時),經過new Date 能夠把這個時間轉換爲北京時間 console.log(headerAll, new Date(serverDate); return; } // 在狀態爲4的時候響應主體內容就已經回來了 if (state === 4){ let valueText = xhr.responseText, // 獲取到的結果通常都是JSON字符串(可使用JSON.PARSE把其轉換爲JSON對象) valueXML = xhr.responseXML; // 獲取到的結果是XML格式的數據(能夠經過XML的一些常規操做獲取存儲的指定信息) // 若是服務器返回的是XML文檔,用responseText獲取的結果是字符串,而用responseXML獲取的是標準XML文檔 console.log(valueText, valueXML); } }; xhr.send('name=hy&age=6&sex=man');
正常的編碼解碼(非加密)
- escape / unescape: 主要就是把中文漢字進行編碼和解碼(通常只有JS語言支持:也常常應用於前端頁面通訊時候的中文漢字編碼)
str = '你好海洋 哈哈' "你好海洋 哈哈" escape(str) "%u4F60%u597D%u6D77%u6D0B%20%u54C8%u54C8" unescape("%u4F60%u597D%u6D77%u6D0B%20%u54C8%u54C8") "你好海洋 哈哈"
- encodeURI / decodeURI : 基本上全部的編程語言都支持
str = '你好海洋 哈哈' "你好海洋 哈哈" encodeURI(str) "%E4%BD%A0%E5%A5%BD%E6%B5%B7%E6%B4%8B%20%E5%93%88%E5%93%88" decodeURI("%E4%BD%A0%E5%A5%BD%E6%B5%B7%E6%B4%8B%20%E5%93%88%E5%93%88") "你好海洋 哈哈"
- encodeURIComponent / decodeURIComponent 和第二種方式很是相似,區別在於:
當咱們經過URL問號傳參的時候,咱們傳遞的參數值仍是一個URL或者包含不少的特殊字符,此時爲了避免影響主要的URL,咱們須要把傳遞的參數值進行編碼,使用encodeURI不能編碼一些特殊字符,因此只能使用恩codeURLComponent處理
str = '你好海洋 哈哈' "你好海洋 哈哈" encodeURIComponent(str) "%E4%BD%A0%E5%A5%BD%E6%B5%B7%E6%B4%8B%20%E5%93%88%E5%93%88" decodeURIComponent("%E4%BD%A0%E5%A5%BD%E6%B5%B7%E6%B4%8B%20%E5%93%88%E5%93%88") "你好海洋 哈哈"
let str = 'http://wudiufo.github.io/?', obj = { name:'haiyang', age:'8'; url:'http://www.haiyang.com/?lx=1' }; // 需求:把obj中的每一項屬性名和屬性值拼接到URL末尾,經過問號傳參的方式 for(let key in obj){ str+=`${key}=${encodeURIComponent(obj[key])}&`; // 不能使用encodeURI,必須使用encodeURIComponent,緣由是encodeURI不能編碼特殊的字符 } console.log(str.replace(/&$/g), ''); // 後期獲取URL問號參數的時候,咱們把獲取的值在依次的解碼便可 String.prototype.myQueryUrlParameter=function myQueryUrlParameter(){ let reg=/[?&]([^?&=]+)(?:=([^?&=]*))?/g, obj={}; this.replace(reg,(...arg)=>{ let [,key,value]=arg; obj[key]=decodeURIComponent(value); //此處獲取的時候能夠進行解碼 }); return obj; }
也能夠經過加密的方法進行編碼解碼
- 可逆轉加密(通常都是團隊本身用的規則)
不可逆轉加密(通常都是基於MD5完成的,可能會把MD5加密後的結果二次加密)
AJAX這個任務:發送請求接收到響應主體內容(完成一個完整的HTTP事務)xhr.send() : 任務開始
xhr.readState===4 : 任務結束
let xhr = new XMLHttpRequest(); xhr.open('get', 'temp.json', false); xhr.onreadystatechange = () =>{ console.log(xhr.readyState); }; xhr.send(); // 只輸出一次結果是4
let xhr = new XMLHttpRequest(); xhr.open('get', 'temp.json', false); xhr.send(); // [同步]開始發送AJAX請求,開啓AJAX任務,在任務沒有完成以前,什麼事情都作不了(下面綁定事件也作不了)=》loading =》當readyState===4的時候AJAX任務完成,開始執行下面的操做 // readyState===4 xhr.onreadystatechange = () =>{ console.log(xhr.readyState); }; // 綁定方法以前狀態已經爲4了,此時AJAX的狀態不會再改變成其餘的值了,因此事件永遠都不會被觸發,一次都沒執行方法(使用AJAX同步編程,不要把send放在事件監聽前,這樣咱們沒法再綁定的方法中獲取到響應主體的內容)
let xhr = new XMLHttpRequest(); xhr.open('get', 'temp.json'); xhr.onreadystatechange = () =>{ console.log(xhr.readyState); }; xhr.send(); // 輸出3次,結果分別是2,3 ,4
let xhr = new XMLHttpRequest(); xhr.open('get', 'temp.json'); xhr.send(); // xhr.readyState===1 xhr.onreadystatechange = () =>{ console.log(xhr.readyState); }; // 2,3,4
let xhr = new XMLHttpRequest(); xhr.onreadystatechange = () =>{ console.log(xhr.readyState); }; xhr.open('get', 'temp.json'); xhr.send(); // 1,2,3,4
let xhr = new XMLHttpRequest(); // xhr.readyState===0 xhr.onreadystatechange = () =>{ console.log(xhr.readyState); }; xhr.open('get', 'temp.json',false); // xhr.readyState===1,AJAX特殊處理了一件事,執行OPEN狀態變爲1,會主動把以前監聽的方法執行一次,而後再去執行SEND xhr.send(); // xhr.readyState===4 AJAX任務結束,住任務隊列完成 // 1,4
1,結構:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="box"></div> <script src="./1.js"></script> </body> </html>
2, 交互:
~ function() { let box = document.getElementById('box'); let serverTime = null; let fn = () => { // 1,計算當前時間和目標時間的差值 // new Date():獲取的是客戶端本機時間(會受到客戶端本身調整時間的影響),重要的時間參考不能基於這個完成,不論哪個客戶端都要基於相同的服務器時間計算 // 每間隔一秒鐘,咱們須要把第一次獲取的服務器時間進行累加 serverTime = serverTime + 1000; let tarTime = new Date('2018/12/22 12:00:00').getTime(), spanTime = tarTime - serverTime; // 2,計算差值中包含多少時分秒 if (spanTime < 0) { // 已經錯過了搶購時間(已經開搶了) box.innerHTML = '開槍'; clearInterval(autoTimer); return; } let hours = Math.floor(spanTime / (1000 * 60 * 60)); spanTime -= hours * 3600000; let minus = Math.floor(spanTime / (1000 * 60)); spanTime -= minus * 60000; let seconds = Math.floor(spanTime / 1000); hours < 10 ? hours = '0' + hours : null; minus < 10 ? minus = '0' + minus : null; seconds < 10 ? seconds = '0' + seconds : null; box.innerHTML = `距離開槍還剩下 ${hours}:${minus}:${seconds}`; }; let autoTimer = setInterval(fn, 1000); // 從服務器端獲取服務器時間 let getServerTime = () => { let xhr = new XMLHttpRequest(); xhr.onreadystatechange = () => { // console.log(xhr.readyState); // HEAD請求方式,狀態碼中沒有3(不須要等待響應主體內容) if (!/^(2|3)\d{2}$/.test(xhr.status)) return; if (xhr.readyState === 2) { serverTime = new Date(xhr.getResponseHeader('date')).getTime(); fn(); } }; xhr.open('head', 'temp.xml', true); xhr.send(null); // 1,服務器返回的時間在響應頭就有,咱們只須要獲取響應頭信息便可,不必獲取響應主體內容,因此請求方式使用HEAD便可 // 2,必須使用異步編程:同步編程咱們沒法再狀態爲2或3的時候作一些處理,而咱們獲取響應頭信息,在狀態爲2的時候就能夠獲取了,因此須要使用異步 // 3,在狀態爲2的時候就把服務器時間獲取到 // 獲取服務器時間總會出現時間差的問題,服務器端把時間記錄好,到客戶端獲取到時間有延遲差(例如:服務器返回的時候記錄的是10:00,到客戶端獲取的時候已是10:01,可是客戶端獲取的結果依然是10:00,這樣就有了1秒鐘的時間差)【儘量的減小時間差,是咱們優化的所有目的】 }; getServerTime(); }();
JQ中AJAX操做詳解
$.ajax({ url:'xxx.txt', //請求API地址 method:'get', //請求方式GET/POST...,在老版本JQ中使用的是type,使用type和method實現的是相同的效果 dataType:'json', //dataType只是咱們預設獲取結果的類型,不會影響服務器的返回,(服務器端通常給咱們返回的都是JSON格式的字符串),若是咱們預設的是JSON,那麼類庫中將把服務器返回的字符串轉換爲JSON對象,若是咱們預設的是text(默認值),咱們把服務器獲取的結果直接拿過來操做便可,咱們預設的值還能夠是xml等 cache:false, // 設置是否清除緩存,只對GET系列請求有做用,默認是true,有緩存,手動設置爲false,無緩存,JQ類庫會在請求URL的末尾追加一個隨機數來清除緩存 data:null, //咱們經過data能夠把一些信息傳遞給服務器;GET系列請求會把data中的內容拼接在URL的末尾經過問號傳參的方式傳遞給服務器,POST系列請求會把內容放在請求主體中傳遞給服務器。data的值能夠設置爲兩種格式:字符串,對象,若是是字符串,設置的值是什麼傳遞給服務器的就是什麼,若是設置的是對象,JQ會把對象變爲 xxx=xxx&xxx=xxx 這樣的字符串傳遞給服務器 async:true,//設置同步或者異步,默認是true表明異步,false是同步 success:function(result){ // 當AJAX請求成功(readyState===4 & status是以2或者4開頭的) // 請求成功後JQ會把傳遞的回調函數執行,而且把獲取的結果當作實參傳遞給回調函數(result就是咱們從服務器獲取的結果) }, error:function(msg){}, // 請求錯誤觸發回調函數 complete:function(){}, // 不論請求是錯誤的仍是正確的都會觸發回調函數(他是完成的意思) })
【支持的參數】
urlmethod/type
data
dataType
async
cache
success
~ function() { class ajaxClass { // SEND AJAX init() { // THIS:EXAMPLE let xhr = new XMLsHttpRequest(); xhr.onreadystatechange = () => { if (!/[23]\d{2}$/.test(xhr.status)) return; if (xhr.readyState === 4) { let result = xhr.responseText; // DATA-TYPE switch (this.dataType.toUpperCase()) { case 'TEXT': case 'HTML': break; case 'JSON': result = JSON.parse(result); break; case 'XML': result = xhr.responseXML; } this.success(result); }; }; // DATA if (this.data != null) { this.formatData(); if (this.isGET) { this.url += this.querySymbol() + this.data; this.data = null; } } // CACHE this.isGET ? this.cacheFn() : null; xhr.open(this.method, this.url, this.async); xhr.send(this.data); } // 把傳遞的對象格式data轉換爲字符串格式的data formatData() { // THIS:EXAMPLE if (Object.prototype.toString.call(this.data) === '[object Object]') { let obj = this.data, str = ``; for (let key in obj) { if (obj.hasOwnProperty(key)) { str += `${key}=${obj[key]}&`; } } str = str.replace(/&$/g, ''); this.data = str; } } cacheFn() { // THIS:EXAMPLE !this.cache ? this.url += `${this.querySymbol()}_=${Math.random()}` : null; } querySymbol() { // THIS:EXAMPLE return this.querySymbol.indexof('?') > -1 ? '&' : '?'; } } // init parameters window.ajax = function({ url = null, method = 'GET', type = 'null', data = null, dataType = 'JSON', cache = true, async = true, success = null } = {}) { let example = new ajaxClass(); example.url = url; example.method = type === null ? method : type; example.data = data; example.dataType = dataType; example.cache = cache; example.async = async; example.success = typeof success === 'function' ? success : new Function(); example.isGET = /^(GET|DELETE|HEAD)$/i.test(example.method); example.init(); return example; }; }(); ajax({});
優化代碼:
~ function() { class ajaxClass { // SEND AJAX init() { // THIS:EXAMPLE let xhr = new XMLHttpRequest(); xhr.onreadystatechange = () => { if (!/[23]\d{2}$/.test(xhr.status)) return; if (xhr.readyState === 4) { let result = xhr.responseText; // DATA-TYPE try { switch (this.dataType.toUpperCase()) { case 'TEXT': case 'HTML': break; case 'JSON': result = JSON.parse(result); break; case 'XML': result = xhr.responseXML; } } catch (e) { } this.success(result); }; }; // DATA if (this.data != null) { this.formatData(); if (this.isGET) { this.url += this.querySymbol() + this.data; this.data = null; } } // CACHE this.isGET ? this.cacheFn() : null; xhr.open(this.method, this.url, this.async); xhr.send(this.data); } // 把傳遞的對象格式data轉換爲字符串格式的data formatData() { // THIS:EXAMPLE if (Object.prototype.toString.call(this.data) === '[object Object]') { let obj = this.data, str = ``; for (let key in obj) { if (obj.hasOwnProperty(key)) { str += `${key}=${obj[key]}&`; } } str = str.replace(/&$/g, ''); this.data = str; } } cacheFn() { // THIS:EXAMPLE !this.cache ? this.url += `${this.querySymbol()}_=${Math.random()}` : null; } querySymbol() { // THIS:EXAMPLE return this.querySymbol.indexof('?') > -1 ? '&' : '?'; } } // init parameters window.ajax = function({ url = null, method = 'GET', type = 'null', data = null, dataType = 'JSON', cache = true, async = true, success = null } = {}) { let _this = new ajaxClass(); ['url', 'method', 'data', 'dataType', 'cache', 'async', 'success'].forEach((item) => { if (item === 'method') { _this.method = type === null ? method : type; return; } if (item === 'success') { _this.success = typeof success === 'function' ? success : new Function(); return; } _this[item] = eval(item); }); _this.isGET = /^(GET|DELETE|HEAD)$/i.test(_this.method); _this.init(); return _this; }; }(); ajax({});