做過前端同學想必都避免不了要和后台server打交道。而以下這三種與后台交互的方式想必大家都不陌生。
Form表單提交,Ajax請求,Angular的$http請求
以前一直搞不清楚什么時候應該用哪種方式請求數據,正好最近在做文件上傳相關業務,順便對這三種方式的使用場景及區別做個簡單總結。
用法
以下是三種請求方式的API詳細介紹:
Form:
https://www.w3schools.com/html/html_forms.asp
Ajax:
http://api.jquery.com/jQuery.ajax/
Angular $http:
https://angular.io/api/common/http
區別
Form VS Ajax, $http
1、提交方式
form表單通常是通過在HTML中定義的action,method及submit來進行表單提交,另外也可以通過在js中調用submit函數來進行表單提交。
具體的提交方式有很多種,比如可以通過封裝成XMLHttpRequest對象進行提交,這里就不一一詳述了。
而另外兩種請求(Ajax,$http)都是基於XMLHttpRequest進行的。
2、頁面刷新
Form提交,更新數據完成后,需要轉到一個空白頁面再對原頁面進行提交后處理。哪怕是提交給自己本身的頁面,也是需要刷新的,因此局限性很大。
Ajax,$http都可以實現頁面的局部刷新,整個頁面不會刷新。
3、請求由誰來提交
Form提交是瀏覽器完成的,無論瀏覽器是否開啟JS,都可以提交表單。
Ajax,$http是通過js來提交請求,請求與響應均由js引擎來處理,因此不啟用JS的瀏覽器,無法完成該操作。
4、是否可以上傳文件
最初,ajax出於安全性考慮,不能對文件進行操作,所以就不能通過ajax來實現文件上傳,但是通過隱藏form提交則可以實現這個功能,所以這也是用隱藏form提交的主要用途。
后來XMLHttpRequest引入了FormData類型,使得通過Ajax也可以實現文件上傳,稍后會詳細介紹。
Ajax VS $http
1、默認Content-type類型
Ajax默認的Content-type是 x-www-form-urlencoded
$http默認的Content-type是 application/json
2、async
Ajax支持同步通信(async:false)
$http不支持async:false
3、參數處理
Ajax在post數據之前jQuery會對數據進行序列化,轉換成字符串:"a=1&b=2"這種形式,然后把post的參數拼接到url上發送。
$http不會對數據做參數處理,數據將以json格式發送。
這樣就會導致一個問題:有些請求通過Ajax可以請求成功,但是通過$http卻失敗了。
當然,我們可以通過做一些處理來實現這兩種請求的統一。
可以從angular層面解決,把angular的post請求也按照jquery的方法做些改變,如下:
http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/
https://github.com/petersirka/total.js/issues/26
通過Ajax提交文件
前面講過,可以通過傳統的form表單實現文件上傳,不過傳統的form表單提交會導致頁面刷新,但是在有些情況下,我們不希望頁面被刷新,
這種時候我們都是使用Ajax的方式進行請求的。
這時候就要用到一個對象FormData。
FormData類型其實是在XMLHttpRequest Level 2定義的,它是為序列化表以及創建與表單格式相同的數據提供的。
目前幾乎所有的主流的瀏覽器都已經支持這個對象了。參見
https://developer.mozilla.org/zh-CN/docs/Web/API/FormData
以下為代碼實現:
<form id="id_form"> <input type="text" name="name"/> <input type="number" name="age"/> <input type="file" name="fileName"/> <input type="button" value="sumbit" onclick="onSubmit();"/> </form>
function onSubmit(){ /* 可以通過兩種方法獲取文件 */ // // 方法一: 直接獲取表單值 // var formData = new FormData(document.getElementById("id_form")); // 方法二:通過FormData的append方法動態添加屬性 var nameVal = $("input[name='name']").val(); var ageVal = $("input[name='age']").val(); var files = document.querySelector('input[type=file]').files;
var formData = new FormData(); formData.append("nameKey", nameVal); formData.append("ageKey", ageVal); formData.append("fileKey", files[0]); /* 可以通過兩種方式實現文件上傳 */ // // 方法一: 通過構建一個XMLHttpRequest對象實現上傳 // var req = new XMLHttpRequest(); // req.open("post", "http://xxx/public/upload", false); // req.send(formData); // 方法二:通過Ajax實現上傳 $.ajax({ url:"http://xxx/public/upload", type:"POST", data:formData, processData:false, contentType:false, success:function(data){ console.log("response success: ", data); }, error:function(error){ alert("response error: ", error); } }); }