【初窺javascript奧秘之Ajax】簡述下你所知道的Ajax?


前言

ajax已經流行很多年了,現在來說它是否已經晚了呢???特別是有這樣框架那樣框架后,還有幾個人認識原生ajax呢?我們每天都會用到的東西你到底對他了解嗎?

在最近一次面試上不幸被問到了,原以為很熟悉的東西你會發現你對他根本不熟悉!要說熟悉AJAX的話你需要毫不猶豫回答以下問題:

1 不同瀏覽器下ajax實現上的差異
2 一次ajax請求過程中有哪幾種狀態值,不同狀態值之間含義是什么
3 ajax在跨域的情況下會出現什么狀況,以及解決方案
4 ajax和后台數據交互時會有什么編碼問題嗎?
5 最后可以說說XMLHttpRequest2有什么新東西

怎么樣?各位能輕易的答上以上4點,便可直接忽略此文,若是只能很含糊的說出1、2點的話,便硬着頭皮看我這篇水文吧,呵呵。

由於本文是邊寫邊實驗的,所以可能會有點亂,也可能會有我的唧唧歪歪的思考過程,請各位見諒。

另外,本人水平還很淺,寫的東西必定有問題,若是文中有任何錯誤以及不足,請請一定指出來,多謝!

ajax簡介

水文還是要有水文的樣子,我這里還是需要簡單介紹一番:

ajax全稱:Asynchronous JavaScript and XML 即傳說中的“異步JavaScript和XML”,他是由html、js、Dom等組成,這一傑出的技術可以將笨拙的web界面變成交互性的ajax應用程序。

ajax是一種構建網站的強大方法,他讓我們桌面上只剩一個瀏覽器的想法不再是空談,不再是妄想,雖說不大可能。。。

曾經我們的頁面需要等待,等待服務器響應,等待屏幕刷新,等待請求返回和生成新頁面。ajax的出現就讓web頁面的等待變得不那么明顯,雖說只是感覺罷了(跟和美女在一起似的,感覺很爽)。。。

在一般的web應用程序中,用戶提交表單后將整個表單發送到服務器,服務器將它轉發給后台腳步(.net,java,php),腳步執行結束后將生成的新的htm頁面返回,這個過程中就會出現我們前面所說的等待:屏幕變得一片空白,等待返回數據在重新繪制,這種交互性就跟你和一個美女XXOO每隔10秒才能動一下似的,這種感受,這種交互性怎一個差字了得???

ajax基本就是把js對象XMLHttpRequest對象放在web表單和服務器之間,當用戶提交數據時只是將數據提交給js,然后由js發送給服務器並獲取返回數據修改頁面,過程中不會出現閃爍、消失或者延遲,傳說中的異步請求。。。

XMLHttpRequest

該js對象為ajax的核心,前面說過了XmlHttpRequest是一套可以在Javascript腳本語言中通過http協議傳送或接收XML及其他數據的一套API。XmlHttp最大的用處是可以更新網頁的部分內容而不需要刷新整個頁面。

首先我們來創建一個xml對象,需要注意兼容,我們先來個管中窺豹:

初始化
 1  <script type="text/javascript">
 2      var xmlHttp = false;

 3      if (window.XMLHttpRequest) {
 4          try {
 5              xmlHttp = new XMLHttpRequest();
 6          } catch (e) {
 7              xmlHttp = false;
 8          }
 9    } else {
10          try {
11              xmlHttp = new ActiveXObject('Msxml2.XMLHTTP');
12          } catch (e) {
13              try {
14                  xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
15              } catch (ee) {
16                  xmlHttp = false;
17              }
18          }
19      }
20  
21      var s = '';
22  </script>

ajax的請求響應模型

ajax基本流程基本如下:

1 從web表單中獲取所需數據(不用表單也行)
2 建立連接url
3 打開服務器連接
4 設置數據返回回調函數
5 發送請求
xmlHttp.open('GET', url, true);
xmlHttp.onreadystatechange = function (e) {};
xmlHttp.send(null)

open時,最后一個參數為true將建立異步連接,false將等待服務器響應

onreadystatechage 可以指定數據返回時回調函數

send便是發送請求,參數便是要傳的參數,沒有參數可以填null

我們來寫段后台程序試試:

前端
 1  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 2  
 3  <html xmlns="http://www.w3.org/1999/xhtml">
 4  <head>
 5      <title></title>
 6  </head>
 7  <body>
 8  
 9  </body>
10  <script type="text/javascript">
11      var xmlHttp = false;
12      function createXMLHttpRequest() {
13          if (window.XMLHttpRequest) {
14              try {
15                  xmlHttp = new XMLHttpRequest();
16              } catch (e) {
17                  xmlHttp = false;
18              }
19          } else {
20              try {
21                  xmlHttp = new ActiveXObject('Msxml2.XMLHTTP');
22              } catch (e) {
23                  try {
24                      xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
25                  } catch (ee) {
26                      xmlHttp = false;
27                  }
28              }
29          }
30      }
31  
32      createXMLHttpRequest();
33      if (xmlHttp) {
34          xmlHttp.open('GET', 'ajax.ashx', true);
35          xmlHttp.onreadystatechange = function (e) {
36              var tmp = xmlHttp.responseText;
37              var s = '';
38          }
39          xmlHttp.send();
40  
41      }
42      
43  
44      var s = '';
45  </script>
46  </html>

 

服務器端代碼
 1 <%@ WebHandler Language="C#" Class="ajax" %>
 2 
 3 using System;
 4 using System.Web;
 5 
 6 public class ajax : IHttpHandler {
 7     
 8     public void ProcessRequest (HttpContext context) {
 9         context.Response.ContentType = "text/plain";
10         string name = context.Request.QueryString["name"] == null ? "" : context.Request.QueryString["name"].ToString();
11         context.Response.Write("ajax 返回:" + name);
12     }
13  
14     public bool IsReusable {
15         get {
16             return false;
17         }
18     }
19 
20 }

其實我們定義的會函數會被執行三次,狀態碼依次返回2,3,4,現在我們來看看這個狀態碼是什么:

xmlHttp.readyState:
0 :未初始化,還沒有調用send()方法 
1 :載入,已調用send()方法,正在發送請求 
2 :載入完成,send()方法執行完成,已經接收到全部響應內容 
3 :交互,正在解析響應內容 
4 :完成,響應內容解析完成,可以在客戶端調用了

意思是我們只需要關注4便可以了。

另外幾次請求返回數據一致可能是因為瀏覽器緩存原因,請各位自己加上隨機數喲。

那些年我們一起跨的域

ajax也會遇到跨域問題的,我們所說的跨域現在一般都是跨域請求數據,跨域提交數據這種事情好像只有html5的postMessage能做。

跨域請求數據的原理是,我們先在我們的頁面上定義一個js函數,然后以script的方式請求數據,數據返回的字符串便會調用我們定義的方法:

xmlHttp.open('POST', 'http://localhost:47389/html5%E5%92%8Ccss3/ajax.ashx', true);

將前面代碼url處做一個修改后,請求就沒有響應了,我們先看看這個url會輸出什么:

跨域
 1 <%@ WebHandler Language="C#" Class="ajax" %>
 2 
 3 using System;
 4 using System.Web;
 5 
 6 public class ajax : IHttpHandler {
 7     
 8     public void ProcessRequest (HttpContext context) {
 9         context.Response.ContentType = "text/plain";
10         context.Response.Write("Hello World");
11     }
12  
13     public bool IsReusable {
14         get {
15             return false;
16         }
17     }
18 
19 }

我們修改下后台代碼:

修改后
 1 <%@ WebHandler Language="C#" Class="ajax" %>
 2 
 3 using System;
 4 using System.Web;
 5 
 6 public class ajax : IHttpHandler {
 7     
 8     public void ProcessRequest (HttpContext context) {
 9         context.Response.ContentType = "text/html";
10         string callback = context.Request.QueryString["callback"] == null ? "callback" : context.Request.QueryString["callback"].ToString();
11         context.Response.Write(callback + "();");
12     }
13  
14     public bool IsReusable {
15         get {
16             return false;
17         }
18     }
19 
20 }

如此便會返回callback字符,

其實,說到異步跨域問題,我感覺就和ajax關系不大了,我想的是這樣做:

跨域后台
 1 <%@ WebHandler Language="C#" Class="ajax" %>
 2 
 3 using System;
 4 using System.Web;
 5 
 6 public class ajax : IHttpHandler {
 7     
 8     public void ProcessRequest (HttpContext context) {
 9         context.Response.ContentType = "text/html";
10         string callback = context.Request.QueryString["callback"] == null ? "callback" : context.Request.QueryString["callback"].ToString();
11         context.Response.Write(callback + "({name: '葉小釵'});");
12     }
13  
14     public bool IsReusable {
15         get {
16             return false;
17         }
18     }
19 
20 }
跨域前台
 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 2 
 3 <html xmlns="http://www.w3.org/1999/xhtml">
 4 <head>
 5     <title></title>
 6 </head>
 7 <body>
 8 
 9 </body>
10 <script type="text/javascript">
11 
12     function callback() {
13         alert('函數回調');
14     }
15     var url = 'http://localhost:47389/html5%E5%92%8Ccss3/ajax.ashx';
16     var scpt = document.createElement('script');
17     scpt.setAttribute('type', 'text/javascript');
18     scpt.setAttribute('src', url);
19     document.getElementsByTagName("head")[0].appendChild(scpt);
20 
21 </script>
22 </html>
23  

如此一來,便跨域了!

針對跨域post的處理,一般是以form target指向一個隱藏的iframe實現的,比如我們最初的文件圖片上傳“ajax”的實現。

編碼問題

若是頁面采用utf-8編碼,而服務器采用gbk的話,也許會出現編碼問題,甚至引起莫名其妙的BUG:

這里便讓中文不能解析。

HTML5中的XMLHttpRequest

老版本缺點:
只支持文本數據的傳送,無法用來讀取和上傳二進制文件。
傳送和接收數據時,沒有進度信息,只能提示有沒有完成。
受到"同域限制"(Same Origin Policy),只能向同一域名的服務器請求數據。
2.0改進
可以設置HTTP請求的時限。 可以使用FormData對象管理表單數據。 可以上傳文件。 可以請求不同域名下的數據(跨域請求)。 可以獲取服務器端的二進制數據。 可以獲得數據傳輸的進度信息。

作為XMLHttpRequest的改進版,IE9都還不支持呢,估計最新的IE10應該沒問題了。

XMLHttpRequest Level2 在功能上有了很大的改進,比如2.0版本可以跨域啦!!!

跨域http請求包含一個origin頭部,他為服務器提供http請求源信息,頭部由瀏覽器保護,不能被程序更改,從本質上講他與跨文檔消息通信中消息事件的origin屬性作用相同。

origin頭部不同於早先的refer,后者referer是一個包含路徑的完整url,路由可能包含敏感信息,瀏覽器不一定發送referer,但一定會發送origin。

算了,以上這塊是抄的,我完全沒有概念,反正意思是按照他的規則玩游戲,你就可以跨域!

我這里想要表達的重點其實是以下功能點:

XMLHttpRequest2.0支持了對進度的響應!確實是進度的響應,他讓我們上傳文件產生進度條變成了可能,之前僅有readystatechage一個事件能給用來響應進度,而且該事件並不兼容,如ie中就不會有狀態3,更別說上傳通信了,這種情況下要實現進度條是一件無比麻煩的事情:

我們來看看現在的事件列表

loadStart
傳輸開始時觸發
progress 上傳過程中觸發,他的e屬性會包含很多有用信息哦。
abort 取消上傳時觸發
error 出錯時觸發
load 接受完數據觸發
loadend
傳輸結束觸發,無論成功與否

若想查看例子請猛擊: 一次上機面試題帶來的感悟【學習的感覺、學習的方法】

此段參考資料:XMLHttpRequest Level 2 使用指南

結語

今天,我們一起學習了AJAX的相關知識,我感覺還是挺有用的。。。。若是有任何錯誤請指出哦。

如果你覺得這篇文章還不錯,請幫忙點擊一下推薦,謝謝!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM