摘要:頁(yè)面發(fā)起一個(gè)到服務(wù)器的請(qǐng)求,然后服務(wù)器一直保持連接打開,直到有數(shù)據(jù)可發(fā)送。
Ajax與Comet XMLHttpRequest對(duì)象
IE5是第一款引入XHR對(duì)象的瀏覽器,在IE5中,XHR對(duì)象是通過MSXML庫(kù)中的一個(gè)ActiveX對(duì)象實(shí)現(xiàn)的
//適用于 IE7 之前的版本 function createXHR(){ if (typeof arguments.callee.activeXString != "string"){ var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"], i, len; for (i=0,len=versions.length; i < len; i++){ try { new ActiveXObject(versions[i]); arguments.callee.activeXString = versions[i]; break; } catch (ex){ //跳過 } } } return new ActiveXObject(arguments.callee.activeXString); }
這個(gè)函數(shù)會(huì)盡力根據(jù)IE中可用的MSXML庫(kù)的情況創(chuàng)建最新版本的XHR對(duì)象
IE7+、Firefox、Opera、Chrome、Safari都支持原生的XHR對(duì)象,這些瀏覽器中創(chuàng)建XHR對(duì)象,可以使用XMLHttpRequest構(gòu)造函數(shù)
var xhr=new XMLHttpRequest();
如果還必須要支持IE的更早版本,可以在createHXR()函數(shù)中加入對(duì)原生XHR對(duì)象的支持
function createXHR(){ if (typeof XMLHttpRequest != "undefined"){ return new XMLHttpRequest(); } else if (typeof ActiveXObject != "undefined"){ if (typeof arguments.callee.activeXString != "string"){ var versions = [ "MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"], i, len; for (i=0,len=versions.length; i < len; i++){ try { new ActiveXObject(versions[i]); arguments.callee.activeXString = versions[i]; break; } catch (ex){ //跳過 } } } return new ActiveXObject(arguments.callee.activeXString); } else { throw new Error("No XHR object available."); } }
這個(gè)函數(shù)中新增的代碼首先檢測(cè)原生XHR對(duì)象是否存在,如果存在則返回它的新實(shí)例,如果原生對(duì)象不存在,則檢測(cè)ActiveX對(duì)象,如果這兩種對(duì)象都不存在,就拋出一個(gè)錯(cuò)誤,然后就可以使用下面的代碼在所有瀏覽器中創(chuàng)建XHR對(duì)象了
var xhr=createXHR();XHR的用法
在使用XHR對(duì)象時(shí),要調(diào)用的第一個(gè)方法是open(),接收3個(gè)參數(shù):要發(fā)送的請(qǐng)求的類型(get或者post)、請(qǐng)求的URL和表示是否異步發(fā)送請(qǐng)求的布爾值
xhr.open("get","example.php",false);
這行代碼會(huì)啟動(dòng)一個(gè)針對(duì)example.php的GET請(qǐng)求
URL相對(duì)于執(zhí)行代碼的當(dāng)前頁(yè)面
open()方法并不會(huì)真正發(fā)送請(qǐng)求,而是啟動(dòng)一個(gè)請(qǐng)求以備發(fā)送
要想發(fā)送特定的請(qǐng)求,調(diào)用send()方法
xhr.open("get","example.txt",false); xhr.send(null);
send()方法接收一個(gè)參數(shù),要作為請(qǐng)求主體發(fā)送的數(shù)據(jù),如果不需要通過請(qǐng)求主體發(fā)送數(shù)據(jù),必須傳入null
響應(yīng)的數(shù)據(jù)會(huì)自動(dòng)填充XHR對(duì)象的屬性
responseText,作為響應(yīng)主體被返回的文本
responseXML,如果響應(yīng)的內(nèi)容類型是"text/xml"或"application/xml",這個(gè)屬性中將保存包含著響應(yīng)數(shù)據(jù)的XML DOM文檔
status,響應(yīng)的HTTP狀態(tài)
statusText,HTTP狀態(tài)的說明
XHR對(duì)象的readyState屬性表示請(qǐng)求響應(yīng)過程的當(dāng)前活動(dòng)階段
0,未初始化,尚未調(diào)用open()方法
1,啟動(dòng),已經(jīng)調(diào)用open()方法,但尚未調(diào)用send()方法
2,發(fā)送,已經(jīng)調(diào)用send()方法,但尚未接收到響應(yīng)
3,接收,已經(jīng)接收到部分響應(yīng)數(shù)據(jù)
4,完成,已經(jīng)接收到全部響應(yīng)數(shù)據(jù),而且已經(jīng)可以在客戶端使用了
必須在調(diào)用open()之前指定onreadystatechange事件處理程序才能確保跨瀏覽器兼容性
var xhr = createXHR(); xhr.onreadystatechange = function(){ if (xhr.readyState == 4){ if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.responseText); } else { alert("Request was unsuccessful: " + xhr.status); } } }; xhr.open("get", "example.txt", true); xhr.send(null);
在接收到響應(yīng)之前還可以調(diào)用abort()方法來取消異步請(qǐng)求
HTTP頭部信息
在發(fā)送XHR請(qǐng)求的同時(shí),還會(huì)發(fā)送下列頭部信息
Accept,瀏覽器能夠處理的內(nèi)容類型
Accept-Charset,瀏覽器能夠顯示的字符集
Accept-Encoding,瀏覽器能夠處理的壓縮編碼
Accept-Language,瀏覽器當(dāng)前設(shè)置的語(yǔ)言
Connection,瀏覽器與服務(wù)器之間連接的類型
Cookie,當(dāng)前頁(yè)面設(shè)置的任何Cookie
Host,發(fā)出請(qǐng)求的頁(yè)面所在的域
Referer,發(fā)出請(qǐng)求的頁(yè)面的URI
User-Agent,瀏覽器的用戶代理字符串
setRequestHeader()方法,可以設(shè)置自定義的請(qǐng)求頭部信息,這個(gè)方法接收兩個(gè)參數(shù):頭部字段名稱和頭部字段的值。要成功發(fā)送頭部信息,必須在調(diào)用open()方法之后且調(diào)用send()方法之前調(diào)用setRequestHeader()
var xhr = createXHR(); xhr.onreadystatechange = function(){ if (xhr.readyState == 4){ if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.responseText); } else { alert("Request was unsuccessful: " + xhr.status); } } }; xhr.open("get", "example.php", true); xhr.setRequestHeader("MyHeader", "MyValue"); xhr.send(null);GET請(qǐng)求
GET是最常見的請(qǐng)求類型,最常用于向服務(wù)器查詢某些信息,必要時(shí)可以將查詢字符串參數(shù)追加到URI的末尾,以便將信息發(fā)送給服務(wù)器
使用GET請(qǐng)求經(jīng)常會(huì)發(fā)生一個(gè)錯(cuò)誤,就是查詢字符串的格式問題。
查詢字符串中每個(gè)參數(shù)的名稱和值都必須使用encodeURIComponent()進(jìn)行編碼,然后才能放到URL的末尾,而且所有的名-值對(duì)都必須由&分隔
xhr.open("get","example.php?name1=value1&name2=value2",true)
向現(xiàn)有URL的末尾添加查詢字符串參數(shù)
function addURLParam(url, name, value) { url += (url.indexOf("?") == -1 ? "?" : "&"); url += encodeURIComponent(name) + "=" + encodeURIComponent(value); return url; }
addURLParam()函數(shù)接收3個(gè)參數(shù):要添加參數(shù)的URL、參數(shù)的名稱和參數(shù)的值
POST請(qǐng)求
POST請(qǐng)求,通常用于向服務(wù)器發(fā)送應(yīng)該被保存的數(shù)據(jù)
function submitData(){ var xhr = createXHR(); xhr.onreadystatechange = function(){ if (xhr.readyState == 4){ if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.responseText); } else { alert("Request was unsuccessful: " + xhr.status); } } }; xhr.open("post", "postexample.php", true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); var form = document.getElementById("user-info"); xhr.send(serialize(form)); }XMLHttpRequest 2級(jí) FormData
FormData為序列化表單以及創(chuàng)建與表單格式相同的數(shù)據(jù),提供了便利
var data=new FormData(); data.append("name","Nicholas");
這個(gè)append()方法接收兩個(gè)參數(shù),鍵和值
創(chuàng)建了FormData的實(shí)例后,可以將它直接傳給XHR的send()方法
var xhr = createXHR(); xhr.onreadystatechange = function(){ if (xhr.readyState == 4){ if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.responseText); } else { alert("Request was unsuccessful: " + xhr.status); } } }; xhr.open("post","postexample.php", true); var form = document.getElementById("user-info"); xhr.send(new FormData(form));超時(shí)設(shè)定
IE8為XHR對(duì)象添加了一個(gè)timeout屬性,表示請(qǐng)求在等待響應(yīng)多少毫秒之后就會(huì)終止,在給timeout設(shè)置一個(gè)數(shù)值后,如果在規(guī)定的時(shí)間內(nèi)瀏覽器還沒有接收到響應(yīng),那么就會(huì)觸發(fā)timeout事件,進(jìn)而會(huì)調(diào)用ontimeout事件處理程序
var xhr = createXHR(); xhr.onreadystatechange = function(){ if (xhr.readyState == 4){ try { if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.responseText); } else { alert("Request was unsuccessful: " + xhr.status); } } catch (ex){ //假設(shè)由 ontimeout 事件處理程序處理 } } }; xhr.open("get", "timeout.php", true); xhr.timeout = 1000; // 將超時(shí)設(shè)置為 1 秒鐘(僅適用于 IE8+ ) xhr.ontimeout = function(){ alert("Request did not return in a second."); }; xhr.send(null);overrideMimeType()方法
Firefox最早引入了overrideMimeType()方法,用于重寫XHR響應(yīng)的MIME類型
通過調(diào)用overrideMimeType()方法,可以保證把響應(yīng)當(dāng)做XML而非純文本來處理
var xhr = createXHR(); xhr.open("get", "text.php", true); xhr.overrideMimeType("text/xml"); xhr.send(null);進(jìn)度事件
6個(gè)進(jìn)度事件
loadstart,在接收到響應(yīng)數(shù)據(jù)的第一個(gè)字節(jié)時(shí)觸發(fā)
progress,在接收響應(yīng)期間持續(xù)不斷地觸發(fā)
error,在請(qǐng)求發(fā)生錯(cuò)誤時(shí)觸發(fā)
abort,在因?yàn)檎{(diào)用abort()方法而終止連接時(shí)觸發(fā)
load,在接收到完整的響應(yīng)數(shù)據(jù)時(shí)觸發(fā)
loadend,在通信完成或者觸發(fā)error、abort或load事件后觸發(fā)
load事件var xhr = createXHR(); xhr.onload = function(){ if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.responseText); } else { alert("Request was unsuccessful: " + xhr.status); } }; xhr.open("get", "altevents.php", true); xhr.send(null);progress事件
var xhr = createXHR(); xhr.onload = function(event){ if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.responseText); } else { alert("Request was unsuccessful: " + xhr.status); } }; xhr.onprogress = function(event){ var divStatus = document.getElementById("status"); if (event.lengthComputable){ divStatus.innerHTML = "Received " + event.position + " of " + event.totalSize +" bytes"; } }; xhr.open("get", "altevents.php", true); xhr.send(null);
為確保正常執(zhí)行,必須在調(diào)用open()方法之前添加onprogress事件處理程序
跨源資源共享CORS,跨資源共享,定義了在必須訪問跨源資源時(shí),瀏覽器遠(yuǎn)服務(wù)器應(yīng)該如何溝通。CORS基本思想就是使用自定義的HTTP頭部讓瀏覽器與服務(wù)器進(jìn)行溝通,從而決定請(qǐng)求或響應(yīng)是應(yīng)該成功還是應(yīng)該失敗
IE對(duì)CORS的實(shí)現(xiàn)
微軟在IE8中引入了XDR類型,這個(gè)對(duì)象與XHR類型,但是能實(shí)現(xiàn)安全可靠的跨域通信
cookie不會(huì)隨請(qǐng)求發(fā)布,也不會(huì)隨響應(yīng)返回
只能設(shè)置請(qǐng)求頭部信息中的Content-Type字段
不能訪問響應(yīng)頭部信息
只支持GET和POST請(qǐng)求
XDR對(duì)象的使用方法與XHR對(duì)象非常相似,也是創(chuàng)建一個(gè)XDomainRequest的實(shí)例,調(diào)用open()方法,再調(diào)用send()方法,與XHR對(duì)象的open()方法不同,XDR對(duì)象的open()方法只接收2個(gè)參數(shù):請(qǐng)求類型和URL
所有XDR請(qǐng)求都是異步執(zhí)行的,不能用它來創(chuàng)建同步請(qǐng)求,請(qǐng)求返回之后,會(huì)觸發(fā)load事件,響應(yīng)的數(shù)據(jù)也會(huì)保存在responseText屬性中
var xdr = new XDomainRequest(); xdr.onload = function(){ alert(xdr.responseText); }; xdr.open("get", "http://www.somewhere-else.com/page/"); xdr.send(null)
請(qǐng)求返回前調(diào)用abort()方法可以終止請(qǐng)求
xdr.abort();//終止請(qǐng)求
與XHR一樣,XDR對(duì)象也支持timeout屬性以及ontimeout事件處理程序
var xdr = new XDomainRequest(); xdr.onload = function(){ alert(xdr.responseText); }; xdr.onerror = function(){ alert("An error occurred."); }; xdr.timeout = 1000; xdr.ontimeout = function(){ alert("Request took too long."); }; xdr.open("get", "http://www.somewhere-else.com/page/"); xdr.send(null);
為支持POST請(qǐng)求,XDR對(duì)象提供了contentType屬性,用來表示發(fā)送數(shù)據(jù)的格式
var xdr = new XDomainRequest(); xdr.onload = function(){ alert(xdr.responseText); }; xdr.onerror = function(){ alert("An error occurred."); }; xdr.open("post", "http://www.somewhere-else.com/page/"); xdr.contentType = "application/x-www-form-urlencoded"; xdr.send("name1=value1&name2=value2");其他瀏覽器對(duì)CORS的實(shí)現(xiàn)
要請(qǐng)求位于另一個(gè)域中的資源,使用標(biāo)準(zhǔn)的XHR對(duì)象并在open()方法中傳入絕對(duì)URL
var xhr = createXHR(); xhr.onreadystatechange = function(){ if (xhr.readyState == 4){ if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.responseText); } else { alert("Request was unsuccessful: " + xhr.status); } } }; xhr.open("get", "http://www.somewhere-else.com/page/", true); xhr.send(null);
安全限制
不能使用setRequsetHeader()設(shè)置自定義頭部
不能發(fā)送和接收cookie
調(diào)用getAllResponseHeaders()方法總會(huì)返回空字符串
Preflighted Requests通過Preflighted Request的透明服務(wù)器驗(yàn)證機(jī)制支持開發(fā)人員使用自定義的頭部、GET和POST之外的方法,以及不同類型的主體內(nèi)容
這種請(qǐng)求使用OPITONS方法,發(fā)送下列頭部
Origin,與簡(jiǎn)單的請(qǐng)求相同
Access-Control-Method,請(qǐng)求自身使用的方法
Access-Control-Headers,自定義的頭部信息,多個(gè)頭部以逗號(hào)分隔
Origin: http://www.nczonline.net Access-Control-Request-Method: POST Access-Control-Request-Headers: NCZ
服務(wù)器可以決定是否允許這種類型的請(qǐng)求,服務(wù)器在響應(yīng)中發(fā)送如下頭部與瀏覽器進(jìn)行溝通
Access-Control-Allow-Origin,與簡(jiǎn)單的請(qǐng)求相同
Access-Control-Allow-Methods,允許的方法,多個(gè)方法以逗號(hào)分隔
Access-Control-Allow-Headers,允許的頭部,多個(gè)頭部以逗號(hào)分隔
Access-Control-Max-Age,應(yīng)該將這個(gè)Preflight請(qǐng)求緩存多長(zhǎng)時(shí)間,以秒表示
Access-Control-Allow-Origin: http://www.nczonline.net Access-Control-Allow-Methods: POST, GET Access-Control-Allow-Headers: NCZ Access-Control-Max-Age: 1728000帶憑據(jù)的請(qǐng)求
通過將withCredentials屬性設(shè)置為true,可以指定某個(gè)請(qǐng)求應(yīng)該發(fā)送憑據(jù)
Access-Control-Allow-Credentials:true
如果發(fā)送的是帶憑據(jù)的請(qǐng)求,但服務(wù)器的響應(yīng)中沒有包含這個(gè)頭部,那么瀏覽器就不會(huì)把響應(yīng)交給JavaScript,于是responseText中將是空字符串,status的值為0,而且會(huì)調(diào)用onerror()事件處理程序
跨瀏覽器的CORSfunction createCORSRequest(method, url){ var xhr = new XMLHttpRequest(); if ("withCredentials" in xhr){ xhr.open(method, url, true); } else if (typeof XDomainRequest != "undefined"){ vxhr = new XDomainRequest(); xhr.open(method, url); } else { xhr = null; } return xhr; } var request = createCORSRequest("get", "http://www.somewhere-else.com/page/"); if (request){ request.onload = function(){ //對(duì) request.responseText 進(jìn)行處理 }; request.send(); }
Firefox、Safari和Chrome中的XMLHttpRequest對(duì)象與IE中的XDomainRequest對(duì)象類似,都提供了夠用的接口,這兩個(gè)對(duì)象共同的屬性方法如下
abort(),用于停止正在進(jìn)行的請(qǐng)求
onerror(),用于替代onreadystatechange檢測(cè)錯(cuò)誤
onload(),用于替代onreadystatechange檢測(cè)成功
responseText(),用于取得響應(yīng)內(nèi)容
send(),用于發(fā)送請(qǐng)求
其他跨域技術(shù) 圖像Ping一個(gè)網(wǎng)頁(yè)可以從任何網(wǎng)頁(yè)中加載圖像,不用擔(dān)心跨域不跨域
通過圖像Ping,瀏覽器得不到任何具體的數(shù)據(jù),但通過偵聽load和error事件,它能知道響應(yīng)什么時(shí)候接收到的
var img = new Image(); img.onload = img.onerror = function(){ alert("Done!"); }; img.src = "http://www.example.com/test?name=Nicholas";
圖像Ping最常用于跟蹤用戶點(diǎn)擊頁(yè)面或動(dòng)態(tài)廣告曝光次數(shù),圖像Ping有兩個(gè)主要的缺點(diǎn),一是只能發(fā)送GET請(qǐng)求,二是無法訪問服務(wù)器的響應(yīng)文本。因此圖像Ping只能用于瀏覽器與服務(wù)器間的單向通信
JSONP
JSONP由兩部分組成:回調(diào)函數(shù)和數(shù)據(jù),回調(diào)函數(shù)是當(dāng)響應(yīng)到來時(shí)應(yīng)該在頁(yè)面中調(diào)用的函數(shù),回調(diào)函數(shù)的名字一般是在請(qǐng)求中指定的,而數(shù)據(jù)就是傳入回調(diào)函數(shù)中的JSON數(shù)據(jù)
function handleResponse(response){ alert("You’re at IP address " + response.ip + ", which is in " + response.city + ", " + response.region_name); } var script = document.createElement("script"); script.src = "http://freegeoip.net/json/?callback=handleResponse"; document.body.insertBefore(script, document.body.firstChild);
優(yōu)點(diǎn)在于能夠直接訪問響應(yīng)文本,支持在瀏覽器與服務(wù)器之間雙向通信
Comet
兩種實(shí)現(xiàn)Comet的方式
長(zhǎng)輪詢
短輪詢時(shí)間線
長(zhǎng)輪詢把短輪詢顛倒了一下。頁(yè)面發(fā)起一個(gè)到服務(wù)器的請(qǐng)求,然后服務(wù)器一直保持連接打開,直到有數(shù)據(jù)可發(fā)送。發(fā)送完數(shù)據(jù)之后,瀏覽器關(guān)閉連接,隨即又發(fā)起一個(gè)到服務(wù)器的新請(qǐng)求,這一過程在頁(yè)面打開期間一直持續(xù)不斷
流
在頁(yè)面的整個(gè)生命周期內(nèi)只使用一個(gè)HTTP連接,具體來說就是瀏覽器向服務(wù)器發(fā)送一個(gè)請(qǐng)求,而服務(wù)器保持連接打開,然后周期性的向?yàn)g覽器發(fā)送數(shù)據(jù)
function createStreamingClient(url, progress, finished){ var xhr = new XMLHttpRequest(), received = 0; xhr.open("get", url, true); xhr.onreadystatechange = function(){ var result; if (xhr.readyState == 3){ //只取得最新數(shù)據(jù)并調(diào)整計(jì)數(shù)器 result = xhr.responseText.substring(received); received += result.length; //調(diào)用 progress 回調(diào)函數(shù) progress(result); } else if (xhr.readyState == 4){ finished(xhr.responseText); } }; xhr.send(null); return xhr; } var client = createStreamingClient("streaming.php", function(data){ alert("Received: " + data); }, function(data){ alert("Done!"); });
這個(gè)createStreamingClient()函數(shù)接收三個(gè)參數(shù):要連接的URL、在接收到數(shù)據(jù)時(shí)調(diào)用的函數(shù)以及關(guān)閉連接時(shí)調(diào)用的函數(shù)
服務(wù)器發(fā)送事件
SSE是圍繞只讀Comet交互推出的API或者模式
var source=new EventSource("myevents.php");
EventSource的實(shí)例有一個(gè)readyState屬性,值為0表示正連接到服務(wù)器,值為1表示打開了連接,值為2表示關(guān)閉了連接
另外還有三個(gè)事件
open,在建立連接時(shí)觸發(fā)
message,在從服務(wù)器接收到新事件時(shí)觸發(fā)
error,在無法建立連接時(shí)觸發(fā)
Web SocketsWeb Sockets的目標(biāo)是在一個(gè)多帶帶的持久連接上提供全雙工、雙向通信
要?jiǎng)?chuàng)建Web Socket,先實(shí)例一個(gè)WebSocket對(duì)象并傳入要連接的URL
var socket = new WebSocket("ws://www.example.com/server.php");
實(shí)例化WebSocket對(duì)象后,瀏覽器會(huì)馬上嘗試創(chuàng)建連接,與XHR類似,WebSocket也有一個(gè)表示當(dāng)前狀態(tài)的readyState屬性,這個(gè)屬性的值與XHR并不相同
WebSocket.OPENING(0),正在建立連接
WebSocket.OPEN(1),已經(jīng)建立連接
WebSocket.CLOSING(2),正在關(guān)閉連接
WebSocket.CLOSE(3),已經(jīng)關(guān)閉連接
WebSocket沒有readystatechange事件,不過有其他事件,對(duì)應(yīng)著不同的狀態(tài),readyState的值永遠(yuǎn)從0開始
要關(guān)閉Web Socket連接,可以在任何時(shí)候調(diào)用close()方法
socket.close();
調(diào)用close()之后,readyState的值立即變?yōu)?,而關(guān)閉連接后就會(huì)變成3
使用send()方法并傳入任意字符串
var socket = new WebSocket("ws://www.example.com/server.php"); socket.send("Hello world!"); //將數(shù)據(jù)序列化為JSON字符串,然后發(fā)送到服務(wù)器 var message = { time: new Date(), text: "Hello world!", clientId: "asdfp8734rew" }; socket.send(JSON.stringify(message)); //當(dāng)服務(wù)器收到消息時(shí),WebSocket對(duì)象就會(huì)觸發(fā)message事件,這個(gè)message事件與其他傳遞消息的協(xié)議類似,也是把返回的數(shù)據(jù)保存在event.data屬性中 socket.onmessage = function(event){ var data = event.data; //處理數(shù)據(jù) };
其他事件
open,在成功建立連接時(shí)觸發(fā)
error,在發(fā)生錯(cuò)誤時(shí)觸發(fā),連接不能持續(xù)
close,在連接關(guān)閉時(shí)觸發(fā)
var socket = new WebSocket("ws://www.example.com/server.php"); socket.onopen = function(){ alert("Connection established."); }; socket.onerror = function(){ alert("Connection error."); }; socket.onclose = function(){ alert("Connection closed."); };SSE與Web Sockets
考慮是使用 SSE 還是使用 Web Sockets 時(shí),可以考慮如下幾個(gè)因素。
首先,你是否有自由度建立和維護(hù) Web Sockets服務(wù)器?因?yàn)?Web Socket 協(xié)議不同于 HTTP,所以現(xiàn)有服務(wù)器不能用于 Web Socket 通信。SSE 倒是通過常規(guī) HTTP 通信,因此現(xiàn)有服務(wù)器就可以滿足需求。
第二個(gè)要考慮的問題是到底需不需要雙向通信。如果用例只需讀取服務(wù)器數(shù)據(jù)(如比賽成績(jī)),那么 SSE 比較容易實(shí)現(xiàn)。如果用例必須雙向通信(如聊天室),那么 Web Sockets 顯然更好。在不能選擇 Web Sockets 的情況下,組合 XHR 和 SSE 也是能實(shí)現(xiàn)雙向通信的。
安全
為確保通過 XHR 訪問的 URL 安全,通行的做法就是驗(yàn)證發(fā)送請(qǐng)求者是否有權(quán)限訪問相應(yīng)的資源
要求以 SSL 連接來訪問可以通過 XHR 請(qǐng)求的資源。
要求每一次請(qǐng)求都要附帶經(jīng)過相應(yīng)算法計(jì)算得到的驗(yàn)證碼。請(qǐng)注意,下列措施對(duì)防范 CSRF 攻擊不起作用。
要求發(fā)送 POST 而不是 GET 請(qǐng)求——很容易改變。
檢查來源 URL 以確定是否可信——來源記錄很容易偽造。
基于 cookie 信息進(jìn)行驗(yàn)證——同樣很容易偽造
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/98093.html
摘要:技術(shù)的核心是對(duì)象即。收到響應(yīng)后,響應(yīng)的數(shù)據(jù)會(huì)自動(dòng)填充對(duì)象的屬性,相關(guān)的屬性有作為響應(yīng)主體被返回的文本。收到響應(yīng)后,一般來說,會(huì)先判斷是否為,這是此次請(qǐng)求成功的標(biāo)志。中的版本會(huì)將設(shè)置為,而中原生的則會(huì)將規(guī)范化為。會(huì)在取得時(shí)報(bào)告的值為。 Ajax(Asynchronous Javascript + XML)技術(shù)的核心是XMLHttpRequest對(duì)象,即: XHR。雖然名字中包含XML,但...
摘要:語(yǔ)法語(yǔ)法可以表示三種類型的值簡(jiǎn)單值使用與相同的語(yǔ)法,可以在中表示字符串?dāng)?shù)值布爾值和。對(duì)象對(duì)象作為一種復(fù)雜數(shù)據(jù)類型,表示的是一組無序的鍵值對(duì)兒。如果字符串長(zhǎng)度超過了個(gè),結(jié)果中將只出現(xiàn)前個(gè)字符。 JSON 語(yǔ)法 JSON語(yǔ)法可以表示三種類型的值 簡(jiǎn)單值:使用與 JavaScript 相同的語(yǔ)法,可以在 JSON 中表示字符串、數(shù)值、布爾值和 null 。但 JSON 不支持 JavaS...
摘要:基本概念語(yǔ)法區(qū)分大小寫,中的一切變量函數(shù)名和操作符都區(qū)分大小寫。要將一個(gè)值轉(zhuǎn)換成對(duì)應(yīng)的值,可以調(diào)用類型包括整數(shù)和浮點(diǎn)數(shù)值,基本數(shù)值字面量格式是十進(jìn)制整數(shù),除了十進(jìn)制外還有八進(jìn)制十六進(jìn)制。八進(jìn)制第一位必須是,十六進(jìn)制第一位必須是。 基本概念 語(yǔ)法 區(qū)分大小寫,ECMAScript中的一切(變量、函數(shù)名和操作符)都區(qū)分大小寫。函數(shù)名不能使用typeof,因?yàn)樗且粋€(gè)關(guān)鍵字,但typeOf...
摘要:操作類名時(shí)可以通過屬性添加刪除和替換類名。如果將可選的參數(shù)設(shè)置為,則表示盡量將元素顯示在視口中部垂直方向。將元素的內(nèi)容滾動(dòng)指定的頁(yè)面高度,具體高度由元素的高度決定。 DOM擴(kuò)展 選擇符API querySelector()方法 querySelector()方法接收一個(gè)CSS選擇符,返回與該模式匹配的第一個(gè)元素,如果沒有找到匹配的元素,返回null //取得body元素 var b...
錯(cuò)誤處理與調(diào)試 錯(cuò)誤處理 try-catch語(yǔ)句 try{ //可能會(huì)導(dǎo)致錯(cuò)誤的代碼 }catch(error){ //在錯(cuò)誤發(fā)生時(shí)怎么處理 } 發(fā)生錯(cuò)誤時(shí)可以顯示瀏覽器給出的信息 try{ window.someNonexistentFunction(); }catch(error){ alert(error.message); } 在try-catch語(yǔ)句中是可選的,但...
閱讀 2532·2023-04-25 14:54
閱讀 602·2021-11-24 09:39
閱讀 1810·2021-10-26 09:51
閱讀 3858·2021-08-21 14:10
閱讀 3485·2021-08-19 11:13
閱讀 2695·2019-08-30 14:23
閱讀 1810·2019-08-29 16:28
閱讀 3360·2019-08-23 13:45