-
同步與非同步
-
同步HTTP請求
- 請求-->顯示-->互動-->暫停-->請求-->顯示-->互動-->暫停 …
-
需要不斷重新刷新整個頁面
- 會出現一段時間的空白
-
非同步HTTP請求
- 請求-->顯示-->互動-->(請求)互動-->(請求)互動…
- 非同步HTTP請求在顯示、執行互動不需要再暫停操作,可以馬上執行所需的互動
- 只向伺服器要求一小部份資料,然後更新頁面的一小部份,
不需要重新刷新整個頁面,也不會出現一段時間的空白
-
非同步好處
-
減輕伺服器的負擔,加快瀏覽速度
- 只給所需
-
帶來更好的用戶體驗
- 更流暢的畫面
- 標準化技術,主流瀏覽器都支援
-
促進頁面呈現與資料分離
- 提高可維護性
-
ajax組成
- ajax不是單一技術,是集4種技術而成,JavaScript、CSS、DOM、XMLHttpRequest。
(或說5種,再加上(X)HTML)
-
ajax技術組成
-
JavaScript
- 通用指令碼語言。是撰寫ajax主要程式語言
-
CSS
- 為Web頁面元素提供視覺化樣式的定義方法,
ajax透過修改CSS樣式,改變使用者介面
-
DOM
- ajax可以在執行時透過DOM來改變使用者介面,或局部更新某個節點
-
XMLHttpRequest
-
XMLHttpRequest物件允許Web開發人員向伺服器以非同步方式取資料,
資料格式通常是XML或是文字,目前較流行為JSON
- JSON
-
XMLHttpRequest物件
- 能夠直接在Client使用Javascript來提出HTTP請求
-
IE內建MSXML剖析器有多個版本,其提供的XMLHttpReqest物物也有多個版本
-
XMLHttpRequest版本
-
2.0(IE5)
- msxml.dll
- Microsoft.XMLHttp
-
2.6
- msxml2.dll
- MSXML2.XMLHttp
-
3.0(IE6)
- msxml3.dll
- MSXML2.XMLHttp.3.0
-
4.0
- msxml4.dll
- MSXML2.XMLHttp.4.0
-
5.0
- msxml5.dll
- MSXML2.XMLHttp.5.0
-
6.0
- msxml6.dll
- MSXML2.XMLHttp.6.0
-
建立XMLHttpRequest物件
-
在Mozilla和Safaris是內建物件
- var xmlHttp=new XMLHttpRequest();
-
在IE6之前是透過ActiveX控制項物件(由MSXML提供)
- var xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
- IE7之後,同時支援原生XMLHttpRequest物件(預設值)和ActiveX控制項物件
- var xmlHttp;
function createXMLHttpRequest(){
if (window.XMLHttpRequest) //支援原生型
xmlHttp = new XMLHttpRequest();
else if (window.ActiveXObject) //IE6以下
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
-
屬性/方法
-
屬性
-
XMLHttpRequest屬性
-
readyState
- 回傳狀態值
- 0
- uninitalized,未初始化
- 1
- loading,載入中
- 2
- loaded,載入完成
- 3
- interactive,可互動
- 4
- completed,完成
- 唯讀屬性,目前狀態
-
responseBody
- 唯讀屬性,取得伺服器的回應,傳回非符號位元組的陣列
-
responseSteam
- 唯讀屬性,取得伺服器的回應,傳回IStream資料流物件
-
responseText
- 唯讀屬性,取得伺服器的回應,傳回字串
-
responseXML
- 唯讀屬性,取得伺服器的回應,傳回XML DOM物件,可作DOM處理
-
status
- 唯讀屬性,取得HTTP狀態碼
- 回傳狀態碼
- 200
- OK,請求成功
- 202
- 請求被接收,但處理未完成
- 400
- 錯誤的請求
- 404
- Not Found,找不到網頁
- 500
- Internal Server Error,內部錯誤
- …其他網頁錯誤碼
-
statusText
- 唯讀屬性,取得HTTP狀態訊息字串
-
onreadystatechange
- 存取屬性,執行readyState屬性改變的事件處理,設定處理的程序
-
方法
-
XMLHttpRequest方法
-
abort()
- 取消目前HTTP請求
-
getAllResponseHeaders()
- 取得全部HTTP標頭內容
-
getResponseHeader("指定Header名稱")
- 取得指定HTTP標頭名稱的內容
-
open("GET|POST","URL",async,userid,pwd)
- 開啟HTTP請求
- GET
- 取得伺服器回應
- POST
- 傳送資料到伺服器
- URL
- 請求的XML文件或伺服端程式(ASP.NET, PHP, JSP...)
- async
- 布林值, 預設true,false表示需要等到伺服器回應後才繼續執行Javascript
- userid, pwd
- 伺服器需要id/password,才需要使用
-
send("參數")
- 傳送HTTP請求到伺服器
- 參數表示要向伺服器發送的資料
- 格式為查詢字串的形式
- var param = "name=Bruce&age=18";
- 在open中指定為GET,則參數作為查詢字串傳送,
如果指定為POST,則作為HTTP的POST方法傳送,
對於send()方法而言,此參數為必需,
如不發送任何資料,請傳送null即可。
- GET
- xmlHttp.send(null);
- POST
- xmlHttp.send(param);
-
setRequestHeader("自訂Header名稱",value)
- 自訂HTTP標頭資料
- 如果使用POST方法,在發送之前必須設定HTTP標頭
- xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
- xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
-
GET/POST
-
function startRequest(){
createXMLHttpRequest(); //建立xmlHttp物件
xmlHttp.open("GET","Demo.aspx");
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState == 4 && xmlHttp.status == 200)
alert("服務器傳回訊息: " + xmlHttp.responseText);
}
xmlHttp.send(null);
}
-
參數
- IE會自動暫存非同步的結果,解決方法是每次非同步請求的URL不同,
我們可以加上一個伺服器不需要的參數,讓每次的URL都不同
- var url = "Demo.aspx?timestamp=" & new Date().getTime();
xmlHttp.open("GET",url, true);
- GET請求如果有參數,直接放入URL網址中
- var queryString = "name=Bruce&age=18";
var url = "Demo.aspx?" + queryString + "×tamp=" + new Date().getTime();
- POST請求有參數,統一放在send()中來傳送
- var queryString = "name=Bruce&age=18";
var url = "Demo.aspx?timestamp=" & new Date().getTime();
xmlHttp.open("POST",url,true);
...
xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
xmlHttp.send(queryString);
- POST方法中文會出現亂碼
- 在IE8與MF3上測試無此問題,但為了相容性還是建議加上解決方法
- 這是因為XMLHttpRequest物件在處理傳回responseText/XML時是使用UTF-8編碼,
建議使用解決方法2,對回傳的資料進行decodeURIComponent()解碼即可
- 解決方法
- 1
- 對要傳送的資料進行兩次encodeURI()編碼,
以解決中文亂碼問題
- ...
xmlHttp.send(encodeURI(encodeURI(queryString)));
- 對傳回資料responseText/XML再進行一次decodeURI()解碼
- ...
responseDiv.innerHTML = decodeURI(xmlHttp.responseText);
- 2
- setRequestHeader直接宣告(charset)使用UTF-8
- xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
xmlHttp.send(queryString);
- 對傳回資料responseText/XML進行decodeURIComponent()解碼
- ...
responseDiv.innerHTML = decodeURIComponent()(xmlHttp.responseXML);
-
onreadystatechange
- ajax的重點在狀態改變後的事件處理函式(handler),
也可以說,這是唯一我們必須自訂(手動)設計程式碼
的地方,換個方向說,我們在請求/回應,而伺服器
回應資料後,我們要如何處理及顯示到網頁上(DOM)
-
同時觸發非同步問題
- 如果我們必須同時觸發(呼叫)多個ajax物件,
因為我們通常都是把建立的ajax物件的xmlHttp宣告為全域變數,
所以可能會產生覆蓋的情況
-
解決
- 就是將xmlHttp宣告為區域變數來處理,
並在收到伺服器資料且處理完後,手動刪除
- function getData(){
var xmlHttp="";
createXMLHttpRequest();
xmlHttp.onreadystatechange = function(){
...
delete xmlHttp;
xmlHttp = null;
}
}
- delete關鍵字
- 刪除物件的property
- The delete operator deletes an object, an object's property, or an element at a specified index in an array.