JavaScript系列----AJAX機制詳解以及跨域通信

来源:http://www.cnblogs.com/shouce/archive/2016/03/08/5252678.html
-Advertisement-
Play Games

1.Ajax 1.1.Ajax簡介 Ajax簡介這一部分我們主要是談一下ajax的起源,ajax是什麼?因為這些是跟技術無關的。所以,大多細節都是一筆帶過。 Ajax的起源? Ajax一詞源於2005年 Jesse James Garrett發表的一篇題為"Ajax:A new Approach t


1.Ajax

1.1.Ajax簡介

  Ajax簡介這一部分我們主要是談一下ajax的起源,ajax是什麼?因為這些是跟技術無關的。所以,大多細節都是一筆帶過。

  Ajax的起源?

  Ajax一詞源於2005年 Jesse James Garrett發表的一篇題為"Ajax:A new Approach to Web Applications".他在這篇文       章中介紹了一種新技術,用他的話說,就是Ajax :Asynchronous JavaScript +XML的縮寫。

  Ajax是什麼?

  這種新技術的主要目的就是為了使前端網頁能夠向伺服器請求額外的數據而不需要卸載頁面。自從這種技術出現以後,微軟率先引入XHR對象(ajax能夠實現的核心對象),然後其他瀏覽器相繼實現這種技術。總而言之,ajax就是一種能非同步通信的技術。

1.2.Ajax的核心對象---XMLHttpRequest

  因為IE5是最先引入這個XHR對象的,當時並沒有事實上的標準。在IE中有三種不同的XHR對象版本:MSXML2.XMLHttp,MSXML2.XMLHttp.3.0和MSXML2.XMLHttp.6.0;

根據這三種版本號,在IE中創建一個XHR對象如下:

複製代碼
function createXHR() { //IE7之前的版本通過這種方式
  var versions = [
    'MSXML2.XMLHttp',
    'MSXML2.XMLHttp.3.0',
    'MSXML2.XMLHttp.6.0'
  ];
  var xhr = null;
  for (var item in versions) {
    try {
      xhr = new ActiveXObject(item); //若不存在該版本,可能會出錯
      if (xhr) break;
    } catch (e) {
      //一般對這種錯誤不做處理
    }
  }
  return xhr;
}
複製代碼

在IE引入這個對象之後,其他瀏覽器廠商也相繼跟隨,這時候XHR對象成為事實上的標準!

跨瀏覽器創建XHR對象;

function createXHttpRequest() {
  if (typeof XMLHttpRequest !== 'undefined') { //不要用 if(XMLHttpRequest){}這種形式,
    return new XMLHttpRequest();              //如果是這種形式在找不到XMLHttpRequest函數的情況下,會報錯。
} else if (typeof ActiveXObject !== 'undefined') { 
return createXHR(); //用到剛纔我們創建的函數
} else { throw new Error('不能創建XMLHttpRequest對象'); } }

 

1.2.XMLHttpRequest的用法

XMLHttpRequest對象的函數有6個:

複製代碼
open("method",url,boolean);
//該方法的三個參數,分別為----提交方式"get"或者"post"等
                //&& url是相對於執行代碼的當前頁面的路徑(使用絕對路徑是允許的)&&是否非同步

send();
//這個方法接收一個參數,這個參數是作為請求主體發送的數據,
//說明: 如果有參數,請使用post方式提交 使用方式如下,send("user="+username+"&pwd="+password); //如果沒有參數,為了相容性考慮,必須在參數中傳入null,即send(null);該方式使用get方式提交

abort();             //取消當前響應,關閉連接並且結束任何未決的網路活動。

                    //這個方法把 XMLHttpRequest 對象重置為 readyState 為 0 的狀態,並且取消所有未決                         //的網路活動。例如,如果請求用了太長時間,而且響應不再必要的時候,可以調用這個方法。

 

getResponseHeader()     

                    //返回指定的 HTTP 響應頭部的值。其參數是要返回的 HTTP 響應頭部的名稱。可以使用任                         //何大小寫來制定這個頭部名字,和響應頭部的比較是不區分大小寫的。

                    //該方法的返回值是指定的 HTTP 響應頭部的值,如果沒有接收到這個頭部或者 readyStat                          //e 小於 3 則為空字元串。如果接收到多個有指定名稱的頭部,這個頭部的值被連接起來並                          //返回,使用逗號和空格分隔開各個頭部的值。

getAllResponseHeaders()              

                   //把 HTTP 響應頭部作為未解析的字元串返回。

                   //如果 readyState 小於 3,這個方法返回 null。否則,它返回伺服器發送的所有 HTTP 響應的

                   //頭部。頭部作為單個的字元串返回,一行一個頭部。每行用換行符 "\r\n" 隔開。

                         

setRequestHeader()

                  //向一個打開但未發送的請求設置或添加一個 HTTP 請求。

複製代碼

 

  XMLHttpRequest對象的屬性有5個:

屬性 描述
responseText 作為響應主題被返回的文本
responseXML 如果相響應的是text/html或者application/xml類型的話,這個屬性將保存著響應的XML文檔
status http的響應狀態碼
statusText http狀態的說明
readyState XMLHttpRequest對象的狀態位 0 1 2 3 4 分別表示5種狀態
timeout 設置超時時間,單位是ms.目前只有IE8+支持---尚未標準化(不推薦使用)

 

  XMLHttpRequest對象的事件屬性onReadyStateChange:-----所有瀏覽器相容

  該屬性監聽的是  XMLHttpRequest對象的readyState屬性的變化: 

  readyState的變化分別對應如下狀態:

  0:尚未初始化。未調用open()之前

  1:啟動。調用open()之後,但是未調用send();

  2:發送。調用send()但是尚未得到響應。

  3:正在接收數據。剛接收到響應數據開始到接收完成之前。

  4: 完成。數據接收完成。

 

複製代碼
xhr.onreadystatechange = function () {
  if (xhr.readyState == 4) {
    if (xhr.status >= 200 && xhr.status <== 300 || xhr.status == 304) {
      alert(xhr.responseText);
      //處理接收的數據
    } else {
      //請求失敗,未得到響應數據
    }
  }
}; //補充說明:註冊事件必鬚髮生在send()以前
複製代碼

 

XMLHttpRequest對象的事件屬性ontimeout -----僅限IE8+,不過最新的主流高版本瀏覽器也已經實現(不推薦使用)

xhr.timeout=1000;//一秒鐘

xhr.ontimeout=functon(){
  //處理代碼
  ......
}

  這種使用方式有個問題需要註意,就是在超時之後,在接收到數據後仍然會觸發onreadystatechange事件,如果在處理onreadychange事件時訪問xhr.status屬性,會出錯。所以我們在訪問該屬性時需要做一下try{}catch處理。但是,因為這個屬性暫不相容,所有我們就不重點講了。

 

XMLHttpRequest對象的事件屬性onload onerror onloadstar onbort onprogress

                                                                                                   -----非IE瀏覽器和IE 10+已實現

       onload在IE8以上可以實現,大部分事件根據readySate變化均可以實現,以上事件只不過是方便使用而已。

 

  onload和onprogress 這兩種事件分別對應著readyState=4和readyState=3的情況,使用方式分別如下: 

複製代碼
     xhr.onload= function (event) {
            //event只包含一個屬性 event.target=xhr;使用方式只是在readyState=4時差不多..
        }
     xhr.onprogress=function(event){
         //event除了包含event.target=xhr之外,還包含三種屬性
         //lengthComputale(進度信息是否可用),position(已接受位元組數)和totalSize(總位元組數).
         
     }

複製代碼
補充:有些事件均可以根據readyState的狀態進行模擬。只有有的瀏覽器進行了方便化處理而已。  

 

3.單向跨域技術 ---CORS

 今天我們這裡講的是客戶端網頁向不在同一個域的伺服器請求數據..客戶端在收到返回的數據時時,用回調函數處理數據。

即:

 1. 客戶端向域外伺服器請求數據

 2.伺服器得到響應後向客戶端發送數據。

 3.客戶端根據返回的數據執行回調函數.

 

 我知道不同域下的iframe也可以進行通信,而且這也是一種跨域通信技術。但是,這種iframe頁面之間的雙向通信,我們在下一個專題裡面講解,今天主要講的是單向通信。

3.1.CORS跨域請求的原理

在用xhr(XMLHttpRequest)對象或者xdr(XDomainRequest)對象,發送域外請求時,大概的實現原理如下圖:

 3.2.IE中CORS技術的實現

 IE8引入了一個XDR類型,這個類型與XHR基本類似,但是其能實現安全可靠地跨域通信。

 XHD的特點:

 1.cookie不會隨請求發送,也不會隨響應返回。

 2.只能設置請求頭部中的Content-Type片段。

 3.不能訪問響應頭部信息。

 4.只是支持get和post請求。

 

 XDR支持onload和onerror事件屬性,且其使用方式和XHR基本一致,不過其open()只接收兩個參數,預設是非同步的。

複製代碼
var xdr = new XDomainRequest();
xdr.onload = function () {
  //處理xdr.responseText
}
xdr.onerror = function () {
};
xdr.open('get', '絕對url');
xhr.send(null);
複製代碼

 

 

3.3.跨瀏覽器的CORS技術實現

在標準瀏覽器中XHR對象就已經可以自動實現跨域請求,但是XHR和XDR的不同之處:

1.XHR可以在設置 withCredentials =true時,瀏覽器會把cookie發送給伺服器,伺服器此時通過設置頭部Access-Control-Allow-Credentials:true時來響應。如果,伺服器不設置這個屬性,則瀏覽器會觸發onerror事件。

2.在回調函數中可以訪問status和statusText屬性,而且支持同步請求。

 以下是實現跨域請求的代碼:

複製代碼
function createCrosRequest(method, url) {
  var xhr = new XMLHttpRequest(); //IE7+
  if ('withCredentials' in xhr) { //IE8-IE9瀏覽器沒有這個屬性
    xhr.open(method, url, true);
  } else if (typeof XDomainRequest != 'undefined') {
    xhr = new XDomainRequest();    //IE
    xhr.open(method, url)
  }
  return xhr;
}
var request=CreateCrosRequest("get","url");
if(request){
request.onload=function(){
//處理request.responseText;
}
request.send(null);
}
複製代碼

4.單向跨域技術 ---JSONP技術

 JSONP技術比較簡單,其主要原理主要是利用script標簽的特性。

 script標簽和image標簽一樣,它們都具有src屬性,而且這個屬性是可跨域的。

 

因為script標簽返回的都是js代碼,且該js代碼會自動執行。所以,如果我們請求返回的數據也是類似一段js代碼的形式,豈不是就可以實現在腳本載入完畢後自動執行。

如果我們的請求,返回的數據是 callback + '(' + json + ')'; 這種形式的數據, 那麼在腳本載入完畢之後也就能自動執行callback()函數了.

4.1.客戶端寫法

複製代碼
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body>
       <button id="button">請求數據</button>
</body>
<script>
    window.onload=function(){
        var button=document.getElementById("ibutton");
        function callback(data){
            //處理data
        }
        button.onclick=function(){
            var script=document.createElement("script");
            script="http://www.sasd.com/json/?callbak=callback"; 
            document.body.insertBefore(script,document.body.firstChild);//載入腳本
            
        }
        
    }
</script>
</html>
複製代碼

   1.客戶端將回調函數名寫入<Script>腳本的url參數中。

   2.script載入的時候會發送跨域請求。

4.2.伺服器端

 1.通過url得到函數名,命名為callback

 2.將請求的數據作為函數的參數格式轉化json格式,命名為。

 3.將返回結果拼接為 callback+"("+json+")"; --------返回的就是填充式的數據,這段數據在腳本中會自動執行。

 4.返回數據.

 

 4.3.JSONP技術的缺點

 1.因為是通過url傳參數,所以請求只能是get類型的。

 2.<script>目前只有onload屬性事件,onerror還沒有統一化,如果載入腳本出錯,客戶端很難得到反饋。

 3.所請求數據的站點必須是可信任的,如果返回的數據段中註入的有惡意的代碼,危害較大,且難以發現。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文翻譯自《effective modern C++》,由於水平有限,故無法保證翻譯完全正確,歡迎指出錯誤。謝謝! 古人曾說事情的真相會讓你覺得很自在,但是在適當的情況下,一個良好的謊言同樣能解放你。這個Item就是這樣一個謊言。但是,因為我們在和軟體打交道,所以讓我們避開“謊言”這個詞,換句話來說
  • 這是對前一個spring小例子的解析
  • App與伺服器的通信介面如何設計得好,需要考慮的地方挺多的,在此根據我的一些經驗做一些總結分享,旨在拋磚引玉。 安全機制的設計 現在,大部分App的介面都採用RESTful架構,RESTFul最重要的一個設計原則就是,客戶端與伺服器的交互在請求之間是無狀態的,也就是說,當涉及到用戶狀態時,每次請求都
  • 我們首先瞭解下什麼是shiro ,Shiro 是 JAVA 世界中新近出現的許可權框架,較之 JAAS 和 Spring Security,Shiro 在保持強大功能的同時,還在簡單性和靈活性方面擁有巨大優勢 Shiro 是一個強大而靈活的開源安全框架,能夠非常清晰的處理認證、授權、管理會話以及密碼加
  • 1 package com.shejimoshi.behavioral.Observer; 2 3 4 /** 5 * 功能:學生觀察者 6 * 時間:2016年3月7日上午10:28:00 7 * 作者:cutter_point 8 */ 9 public interface Student 10
  • 在css開始設計的時候,多想想那些可以是繼承的,可以節省很多的代碼,維護也方便。 1) 所有的text 相關屬性都被繼承:如 font-family font-size; font-style;font-weight;font;font-variant;letter-spacing.line-hei
  • <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text
  • 在設計的過程中第一步就是先排版構建框架,後利用CSS對各個塊進行定位。不過各個樣式的id和class博客園本身已經定義好了,我們可以在設置面板中勾選禁用模板預設CSS”覆選框。然後刷新博客首頁查看源碼,將代碼copy到dw上修改樣式。最後將自己修改滿意好的css樣式貼到“管理”-“博客設置”中“通過
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...