在所有主流的網站,基本上都用到了ajax技術,通過異步請求數據已經是一個很普及的實現方式。市面上主流的web前端框架也都有自己封裝的ajax,而且都是大同小異的。也就是說,Ajax這個輪子已經是多的不能再多了,那為什么我們還要自己封裝一個Ajax呢?
想要了解一個技術或者某個功能的實現原理,只有動手實踐才能真正的了解。就如我在csdn上第一篇博客的博文描述。探索技術的路上本應該自己造輪子,即使市面上有再多的選擇,自己動手嘗試也是必要的,第一次嘗試必然會問題眾多,但你不覺得解決他是一件很有成就感的事情嗎,這樣才能帶給你更大的進步和更深刻的領悟。
廢話不說,先來寫一個最基礎的ajax:
[javascript] view plain copy
一個ajax出爐了,通過調用、填寫參數即可請求到服務器。先來分析一下這個ajax的結構,可以看得出來,其實很簡單,只是new了一個XMLHttpRequest對象,然后通過onreadystatechange方法來處理返回值,現在我們只是做了一個判斷,當請求成功時就調用success方法,如果請求失敗,我們還沒有寫上去,后面我們慢慢完善這個ajax的邏輯。
然后調用ajax的open方法,open方法里有三個參數,第一個是請求方式(如:get或post),第二個是請求的url地址,第三個是一個bool值,是否要異步請求。
最后使用send方法帶上參數發送請求即可。
這是,我的服務器已經收到一個請求,但他報了404錯誤,也就是找不到對應的頁面或路由,這時success方法也不會被調用執行。
那我們再來完善一下這個新生的ajax。我們只需要在onreadystatechange方法里增加一個條件,當請求不成功時調用自身的error方法:
[javascript] view plain copy
這樣我們就可以在ajax請求的時候加上error方法,當ajax請求失敗的時候執行我們想要執行的操作?,F在我們拋除跨域請求的問題,當你發送post請求時,你會發現后臺接收不到傳過來的參數,調用如下:
[javascript] view plain copy
后端打印一下傳過來的參數,為空。
出現這個問題的原因主要是請求頭沒有聲明,這時候我們需要初始化聲明一下請求頭,那我們加入一行代碼:
[javascript] view plain copy
設置Conten-type為application/x-www-form-urlencoded,現在后端應該是已經可以收到參數了。那我們現在的ajax調用時實在太繁瑣,有些東西我們不想填的我們應該給他設置一個默認值,不然就會報錯。
比如error方法、method、還有是否異步的bool值等等。那我們再加入一些默認值,現在的ajax是這樣的:
[javascript] view plain copy
現在的ajax還存在一個問題,在post請求的時候,如果我們要傳參,是需要通過字符串傳參的。那這種的書寫規則并不是很友好的:
[javascript] view plain copy
而一般框架的傳參都是通過json的格式來輸入的,我們也不能偏離大眾習慣搞獨立,當然我們也要保留字符串的傳參方式,只是要擴展功能。
那我們需要加一個控制格式的參數,我們這里用dataType這個參數來控制傳參格式,默認是字符串格式傳參好了,可以選擇json格式進行傳參即可。如果是json格式傳參,我們需要把json轉化成字符串類型,代碼如下:
[javascript] view plain copy
這樣,我們的ajax也就可以通過json格式進行傳參了?,F在的ajax完整代碼和調用方式如下:
[javascript] view plain copy
現在這個Ajax基本上已經可以滿足業務上的所以需求,不過還有一點沒有實現,我們的Ajax不能設置請求頭?!為了一些特殊需求的情況下,我們還是要把這一功能加上的:
[javascript] view plain copy
現在的完整代碼入下:
[javascript] view plain copy
完整示例代碼文件:JavaScript封裝Ajax完整示例代碼
JAX上傳的用戶體驗更好,HTML上傳用戶使用更方便一點,直接在網頁里面就能夠操作了。示例在下面提供了,是完整的源代碼,有教程,有視頻教程,基本上使用非常簡單,開發也非常簡單,有技術支持,
網上搜了一下,基本上講這塊的文章還是很多,但是就是一個字亂,講的很混亂。也沒有提供完整的前后端示例。
用戶上傳的文件比較大,有20G左右,直接用HTML傳的話容易失敗,服務器也容易出錯,需要分片,分塊,分割上傳。也就是將一個大的文件分成若干個小文件塊來上傳,另外就是需要實現秒傳功能和防重復功能,秒傳就是用戶如果上傳過這個文件,那么直接在數據庫中查找記錄就行了,不用再上傳一次,節省時間,實現的思路是對文件做MD5計算,將MD5值保存到數據庫,算法可以用MD5,或者CRC,或者SHA1,這個隨便哪個算法都行。
分片還需要支持斷點續傳,現在HTML5雖然提供了信息記錄功能,但是只支持到了會話級,也就是用戶不能關閉瀏覽器,也不能清空緩存。但是有的政府單位上傳大文件,傳了一半下班了,明天繼續傳,電腦一關結果進度信息就丟失了,這個是他們的一個痛點。
切片的話還有一點就是在服務器上合并,一個文件的所有分片數據上傳完后需要在服務器端進行合并操作。
1.下載示例
https://gitee.com/xproer/up6-vue-cli
將up6組件復制到項目中
示例中已經包含此目錄
1.引入up6組件
2.配置接口地址
接口地址分別對應:文件初始化,文件數據上傳,文件進度,文件上傳完畢,文件刪除,文件夾初始化,文件夾刪除,文件列表
參考:http://www.ncmem.com/doc/view.aspx?id=e1f49f3e1d4742e19135e00bd41fa3de
3.處理事件
啟動測試
啟動成功
效果
數據庫
jQuery的Ajax請求實際上是封裝的一個XHLHttpRequest,從字面意思來看是,XML是一種文件格式,Http是一個網絡請求,Request最開始是用于請求XML文件的,后來不斷擴展可以請求多種類型的文件。
XHLHttpRequest,網絡請求模塊,或者是一個瀏覽器網絡線程。用于從URL網絡上獲取數據,有了對象,就可以實現頁面的無刷新請求數據,就可以做到一個局部的更新,也可以獲取多種類型的數據(ftp、文件)。
它是一個對象,首先我們需要實例化,定義一個:
var xhr = new XMLHttpRequest();
//Ajax請求時的參數設置 method 請求方式 url 請求地址 async 是否異步 user 用戶名 password 密碼 ? xhr.open(method,url,async,user,password);
xhr.send(data); 等待接收
一般有如下屬性:
是一個文件,如果響應頭內容是text/xml,這個屬性將保留響應數據的XML、DOM文檔。
xhr.onreadystatechange = () => { if (xhr.readyStatus === 4) { /* HTTP 狀態在 200-300 之間表示請求成功 */ /* HTTP 狀態為 304 表示請求內容未發生改變,可直接從緩存中讀取 */ if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) { console.log('請求成功', xhr.responseText) } } }
function ajax (options) { /* 獲取請求地址 */ let url = options.url; /* 獲取請求方法 */ const method = options.method.toLocaleLowerCase() || 'get'; /* 默認異步 */ const async = options.async != false; /* 獲取請求request數據 */ const data = options.data; /* 實例化XMLHttpRequest */ const xhr = new XMLHttpRequest(); /* 設置超時時間 */ if (options.timeout && options.timeout > 0) { xhr.timeout = options.timeout } ? return new Promise ( (resolve, reject) => { /* 添加超時回調 */ xhr.ontimeout = () => reject && reject('請求超時'); /* 成功回調 */ xhr.onreadystatechange = () => { if (xhr.readyState == 4) { if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) { resolve && resolve(xhr.responseText); } else { reject && reject(); } } } ? /* 失敗回調 */ xhr.onerror = err => reject && reject(err); ? /* 拼接參數 */ let paramArr = []; let encodeData; if (data instanceof Object) { for (let key in data) { paramArr.push( encodeURIComponent(key) + '=' + encodeURIComponent(data[key]) ); } encodeData = paramArr.join('&'); } ? /* get請求 */ if (method === 'get') { const index = url.indexOf('?') if (index === -1) url += '?' else if (index !== url.length -1) url += '&' url += encodeData } ? /* 初始化請求 */ xhr.open(method, url, async); ? /* get直接發送拼接的URL */ if (method === 'get') xhr.send(null); ? if (method === 'post') { xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded;charset=UTF-8') xhr.send(encodeData) } }) }
總結:關于網絡請求,一般常用的有四種:
一個是get,獲取網絡資源
然后是post,一般用于提交數據,提交數據的參數是放在請求的body里面的
delete,刪除
put,標準的一個修改
關于Http的簡單請求和非簡單請求或者是跨域,在跨域時由于瀏覽器的安全機制,涉及到一個問題關于在Ajax請求 ,是在請求之后還是請求之前判斷跨域,這時候就需要了解一下簡單請求和復雜請求。
簡單請求是先把資源請求回來,然后再去判斷是否跨域。如果是一個復雜請求,瀏覽器會先去發送一個嗅探或者是欲請求(一般是一個option),先判斷是否跨域,如果不是跨域那就執行,如果是跨域那就直接不請求了。一般來講,如果get不修改它的Content-Type,那么基本上都是簡單請求。post如果采用www-form的形式,也是一個簡單請求。
這篇文章主要是分享了Javascript中XMLHttpRequest對象的基本屬性和方法, 從實例化、初始化、發送和接受四個階段完成了Ajax網絡請求核心內容封裝。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。