HTML5 ä¸ postMessage sendMessage ç¨æ³
Web Workers
Web Workers ç®ä»
è³ 2008 å¹´ W3C å¶å®åºç¬¬ä¸ä¸ª HTML5 èæ¡å¼å§ï¼HTML5 æ¿è½½äºè¶æ¥è¶å¤å´æ°çç¹æ§ååè½ãå®ä¸ä½å¼ºåäº Web ç³»ç»æç½é¡µçè¡¨ç°æ§è½ï¼èä¸è¿å¢å äºå¯¹æ¬å°æ°æ®åºç Web åºç¨åè½çæ¯æãå ¶ä¸ï¼æéè¦çä¸ä¸ªä¾¿æ¯å¯¹å¤çº¿ç¨çæ¯æãå¨ HTML5 䏿åºäºå·¥ä½çº¿ç¨ï¼Web Workersï¼çæ¦å¿µï¼å¹¶ä¸è§èåº Web Workers çä¸å¤§ä¸»è¦ç¹å¾ï¼è½å¤é¿æ¶é´è¿è¡ï¼ååºï¼ï¼çæ³çå¯å¨æ§è½ä»¥åçæ³çå åæ¶èãWeb Workers å 许å¼å人åç¼åè½å¤é¿æ¶é´è¿è¡èä¸è¢«ç¨æ·æä¸æçåå°ç¨åºï¼å»æ§è¡äºå¡æè é»è¾ï¼å¹¶åæ¶ä¿è¯é¡µé¢å¯¹ç¨æ·çåæ¶ååºã
Web Workers 为 Web å端ç½é¡µä¸çèæ¬æä¾äºä¸ç§è½å¨åå°è¿ç¨ä¸è¿è¡çæ¹æ³ã䏿¦å®è¢«å建ï¼Web Workers å°±å¯ä»¥éè¿ postMessage å任塿± åéä»»å¡è¯·æ±ï¼æ§è¡å®ä¹ååéè¿ postMessage è¿åæ¶æ¯ç»åå»ºè æå®çäºä»¶å¤çç¨åº ( éè¿ onmessage è¿è¡æè· )ãWeb Workers è¿ç¨è½å¤å¨ä¸å½±åç¨æ·çé¢çæ åµä¸å¤çä»»å¡ï¼å¹¶ä¸ï¼å®è¿å¯ä»¥ä½¿ç¨ XMLHttpRequest æ¥å¤ç I/Oï¼ä½é常ï¼åå°è¿ç¨ï¼å æ¬ Web Workers è¿ç¨ï¼ä¸è½å¯¹ DOM è¿è¡æä½ã妿叿åå°ç¨åºå¤ççç»æè½å¤æ¹å DOMï¼åªè½éè¿è¿åæ¶æ¯ç»å建è çåè°å½æ°è¿è¡å¤çã
æµè§å¨å¯¹ HTML5 æ¯ææ åµå¯ä»¥åèç½ç« When can I use...
å¨ Web Workers ä¸ä½¿ç¨ postMessage å onmessage
é¦å ï¼éè¦å¨å®¢æ·ç«¯é¡µé¢ç JavaScript 代ç ä¸ new ä¸ä¸ª Worker å®ä¾åºæ¥ï¼åæ°æ¯éè¦å¨å¦ä¸ä¸ªçº¿ç¨ä¸è¿è¡ç JavaScript æä»¶åç§°ãç¶åå¨è¿ä¸ªå®ä¾ä¸çå¬ onmessage äºä»¶ãæåå¦ä¸ä¸ªçº¿ç¨ä¸ç JavaScript å°±å¯ä»¥éè¿è°ç¨ postMessage æ¹æ³å¨è¿ä¸¤ä¸ªçº¿ç¨é´ä¼ éæ°æ®äºã
æ¸ å 1. 主线ç¨ä¸å建 Worker å®ä¾ï¼å¹¶çå¬ onmessage äºä»¶
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <title>Test Web worker</title> <script type="text/JavaScript"> function init(){ var worker = new Worker('compute.js'); //event 忰䏿 data 屿§ï¼å°±æ¯å线ç¨ä¸è¿åçç»ææ°æ® worker.onmessage= function (event) { // æå线ç¨è¿åçç»ææ·»å å° div ä¸ document.getElementById("result").innerHTML += event.data+"<br/>"; }; } </script> </head> <body onload="init()"> <div id="result"></div> </body> </html>
å¨å®¢æ·ç«¯ç compute.js ä¸ï¼åªæ¯ç®åçéå¤å¤æ¬¡å åæä½ï¼æåéè¿ postMessage æ¹æ³æç»æè¿åç»ä¸»çº¿ç¨ï¼ç®çå°±æ¯çå¾ ä¸æ®µæ¶é´ãèå¨è¿æ®µæ¶é´å ï¼ä¸»çº¿ç¨ä¸åºè¯¥è¢«é»å¡ï¼ç¨æ·å¯ä»¥éè¿ææ½æµè§å¨ï¼åå¤§ç¼©å°æµè§å¨çªå£çæä½æµè¯è¿ä¸ç°è±¡ãè¿ä¸ªéé»å¡ä¸»çº¿ç¨çç»æå°±æ¯ Web Workers æ³è¾¾å°çç®çã
æ¸ å 2. compute.js ä¸è°ç¨ postMessage æ¹æ³è¿å计ç®ç»æ
var i=0; function timedCount(){ for(var j=0,sum=0;j<100;j++){ for(var i=0;i<100000000;i++){ sum+=i; } } // è°ç¨ postMessage å主线ç¨åéæ¶æ¯ postMessage(sum); } postMessage("Before computing,"+new Date()); timedCount(); postMessage("After computing,"+new Date());
å¾ 1. æµè§å¨ä¸è¿è¡ç»æ
Cross-document messaging
Cross-document messaging ç®ä»
ç±äºåæºçç¥çéå¶ï¼JavaScript è·¨åçé®é¢ï¼ä¸ç´æ¯ä¸ä¸ªé¢ä¸ºæ£æçé®é¢ãHTML5 æä¾äºå¨ç½é¡µææ¡£ä¹é´äºç¸æ¥æ¶ä¸åéä¿¡æ¯çåè½ã使ç¨è¿ä¸ªåè½ï¼åªè¦è·åå°ç½é¡µæå¨çªå£å¯¹è±¡çå®ä¾ï¼ä¸ä» åæºï¼å + 端å£å·ï¼ç Web ç½é¡µä¹é´å¯ä»¥äºç¸éä¿¡ï¼çè³å¯ä»¥å®ç°è·¨åéä¿¡ã è¦æ³æ¥æ¶ä»å ¶ä»çªå£å鿥çä¿¡æ¯ï¼å¿ 须对çªå£å¯¹è±¡ç onmessage äºä»¶è¿è¡çå¬ï¼å ¶å®çªå£å¯ä»¥éè¿ postMessage æ¹æ³æ¥ä¼ éæ°æ®ãè¯¥æ¹æ³ä½¿ç¨ä¸¤ä¸ªåæ°ï¼ç¬¬ä¸ä¸ªåæ°ä¸ºæåéçæ¶æ¯ææ¬ï¼ä½ä¹å¯ä»¥æ¯ä»»ä½ JavaScript 对象ï¼éè¿ JSON 转æ¢å¯¹è±¡ä¸ºææ¬ï¼ï¼ç¬¬äºä¸ªåæ°ä¸ºæ¥æ¶æ¶æ¯ç对象çªå£ç URL å°åï¼å¯ä»¥å¨ URL å°åå符串ä¸ä½¿ç¨éé 符'*'æå®å ¨é¨å°ã
å¨ Cross-document messaging ä¸ä½¿ç¨ postMessage å onmessage
为äºå®ç°ä¸ååä¹é´çéä¿¡ï¼éè¦å¨æä½ç³»ç»ç hosts æä»¶æ·»å 两个ååï¼è¿è¡æ¨¡æã
æ¸ å 3. hosts æä»¶ä¸æ·»å 两个ä¸åçåå
127.0.0.1 parent.com 127.0.0.1 child.com
å¨ç¶ç½é¡µä¸éè¿ iframe åµå ¥å页é¢ï¼å¹¶å¨ JavaScript 代ç ä¸è°ç¨ postMessage æ¹æ³åéæ°æ®å°åçªå£ã
æ¸ å 4. ç¶é¡µé¢ä¸åµå ¥å页é¢ï¼è°ç¨ postMessage æ¹æ³åéæ°æ®
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Test Cross-domain communication using HTML5</title> <script type="text/JavaScript"> function sendIt(){ // éè¿ postMessage ååçªå£åéæ°æ® document.getElementById("otherPage").contentWindow .postMessage( document.getElementById("message").value, "http://child.com:8080" ); } </script> </head> <body> <!-- éè¿ iframe åµå ¥åé¡µé¢ --> <iframe src="http://child.com:8080/TestHTML5/other-domain.html" id="otherPage"></iframe> <br/><br/> <input type="text" id="message"><input type="button" value="Send to child.com" onclick="sendIt()" /> </body> </html>
å¨åçªå£ä¸çå¬ onmessage äºä»¶ï¼å¹¶ç¨ JavaScript å®ç°æ¾ç¤ºç¶çªå£åéè¿æ¥çæ°æ®ã
æ¸ å 5. åçªå£ä¸çå¬ onmessage äºä»¶ï¼æ¾ç¤ºç¶çªå£åéæ¥çæ°æ®
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Web page from child.com</title> <script type="text/JavaScript"> //event 忰䏿 data 屿§ï¼å°±æ¯ç¶çªå£åéè¿æ¥çæ°æ® window.addEventListener("message", function( event ) { // æç¶çªå£åéè¿æ¥çæ°æ®æ¾ç¤ºå¨åçªå£ä¸ document.getElementById("content").innerHTML+=event.data+"<br/>"; }, false ); </script> </head> <body> Web page from http://child.com:8080 <div id="content"></div> </body> </html>
å¾ 2. ç¶çªå£åµå ¥åçªå£
å¾ 3. ç¶çªå£åéæ°æ®å°åçªå£
WebSockets
WebSockets ç®ä»
å¨ Web åºç¨ä¸ï¼HTTP åè®®å³å®äºå®¢æ·ç«¯åæå¡ç«¯è¿æ¥æ¯çè¿æ¥ï¼å³å®¢æ·ç«¯ Requestï¼æå¡ç«¯ Responseï¼è¿æ¥æå¼ãè¦æ³å®ç°å®¢æ·ç«¯åæå¡ç«¯å®æ¶éä¿¡ï¼åªè½éè¿å®¢æ·ç«¯è½®è¯¢æ¥å®ç°ãæå¡ç«¯æ¨éæ°æ®ä¹å¹¶ä¸æ¯åé¢ä¸ææä¸çç´æ¥æ¨ï¼å ¶å®è¿æ¯å®¢æ·ç«¯èªå·±åãWebSockets æ¯ HTML5 è§èæ°å¼å ¥çåè½ï¼ç¨äºè§£å³æµè§å¨ä¸åå°æå¡å¨ååé讯çé®é¢ï¼ä½¿ç¨ WebSockets ææ¯ï¼åå°å¯ä»¥éæ¶åå端æ¨éæ¶æ¯ï¼ä»¥ä¿è¯ååå°ç¶æç»ä¸ã
å¨ WebSockets ä¸ä½¿ç¨ send å onmessage
ç±äºææ¬ä¸»è¦ä»ç» postMessage(send) å onmessage 客æ·ç«¯ API çåºç¨ï¼è WebSockets æ¶åå°æå¡å¨ç«¯ä»£ç çå®ç°ï¼æä»¥æ¬æå°éåæç®åçæå¡å¨ç«¯æ¡æ¶æ¥ç¼åæå¡å¨ä»£ç ãWebSockets æå¡å¨ç«¯æ jetty æä¾çåºäº Java çå®ç°ï¼æ WebSocket-Node åºäº node.js çå®ç°ï¼å¨ .Net 4.5 ä¸ä¹ç´æ¥æä¾äº WebSockets çæ¯æãæ¬æå°ä½¿ç¨ WebSocket-Node æä¾ç示ä¾ä»£ç ï¼ç¨ä½ä¿®æ¹ä½ä¸º WebSockets çæå¡å¨ç«¯ãå ³äº node.js çä»ç»ä»¥å使ç¨è¯·åè node.js 宿¹ç½ç« node.jsï¼å ³äº WebSocket-Node ç使ç¨è¯·åè WebSocket-Nodeã
é¦å ï¼éè¦å¨å®¢æ·ç«¯éè¿ JavaScript 代ç new ä¸ä¸ª WebSocket å®ä¾åºæ¥ï¼åæ°æ¯å®ç° WebSocket æå¡å¨ç«¯ URL å°åãç¶åå¨è¿ä¸ªå®ä¾ä¸çå¬ onmessage äºä»¶æ¥æ¶æå¡å¨ç«¯åéè¿æ¥çæ°æ®ãå½ç¶ï¼å®¢æ·ç«¯ä¹å¯ä»¥è°ç¨ send æ¹æ³ï¼åéæ°æ®å°æå¡å¨ç«¯ã
æ¸ å 6. å建 WebSocket 对象ï¼å¹¶çå¬ onmessage äºä»¶
connect : function() { var location ="ws://localhost:8000/"; // å建 WebSockets å¹¶ä¼ å ¥ WebSockets server å°å this._ws =new WebSocket(location); this._ws.onmessage=this._onmessage; //WebSockets è¿æä¾äº onopen 以å onclose äºä»¶ this._ws.onopen =this._onopen; this._ws.onclose =this._onclose; }
å¨ _onmessage æ¹æ³ä¸ï¼æ¥æ¶æ°æ®ï¼å¹¶æ¾ç¤ºå¨é¡µé¢ä¸
æ¸ å 7. _onmessage æ¹æ³
_onmessage : function(event) { //event 忰䏿 data 屿§ï¼å°±æ¯æå¡å¨åéè¿æ¥çæ°æ® if (event.data) { var messageBox = document.getElementById('messageBox'); var spanText = document.createElement('span'); spanText.className ='text'; // ææå¡å¨åéè¿æ¥çæ°æ®æ¾ç¤ºå¨çªå£ä¸ spanText.innerHTML = event.data; var lineBreak = document.createElement('br'); messageBox.appendChild(spanText); messageBox.appendChild(lineBreak); messageBox.scrollTop = messageBox.scrollHeight - messageBox.clientHeight; } },
å¨ _onopen æ¹æ³ä¸ï¼è°ç¨ _send æ¹æ³åé䏿¡æ¶æ¯å°æå¡å¨ç«¯ï¼åä¹è¿æ¥å·²ç»å»ºç«ãå¨ _onclose æ¹æ³ä¸ï¼æ WebSocket çå®ä¾è®¾ç½®æ nullï¼éæ¾èµæºã
æ¸ å 8. _onopenï¼_onclose 以å send æ¹æ³
_onopen : function() { server._send("Client:Open WebSockets,"+new Date()); }, //message åæ°å°±æ¯å®¢æ·ç«¯åæå¡å¨ç«¯åéçæ°æ® _send : function(message) { if (this._ws) this._ws.send(message); }, // æ¤æ¹æ³æä¾å¤é¨ä»£ç è°ç¨ send : function(text) { if (text !=null&& text.length >0) server._send(text); }, _onclose : function(m) { this._ws =null; }
æè¿äºæ¹æ³å°è£ å¨ä¸ä¸ª server 对象ä¸ï¼æ¹ä¾¿æä¾å¤é¨è°ç¨ãç¨æ·åªéè¦å è°ç¨ server ç connect æ¹æ³å»ºç«è¿æ¥ï¼ç¶åè°ç¨ send æ¹æ³åéæ°æ®ã
æ¸ å 9. å°è£ 客æ·ç«¯å®ç°
var server = { // 对å¤ä¸»è¦æä¾ connect å send æ¹æ³ connect : function() {...}, _onopen : function() {...}, _send : function(message) {...}, send : function(text) {...}, _onmessage : function(event) {...}, _onclose : function(m) {...} };
卿å¡å¨ç«¯ï¼éè¿ JavaScript è¯è¨ç®åä¿®æ¹ WebSocket-Node 䏿ä¾ç echo-server.js 示ä¾å³å¯ãè¿éåªå±ç¤ºå ³é®ä»£ç é¨åï¼å ¶å®ä»£ç 请åè§ WebSocket-Node 示ä¾ã
æ¸ å 10. WebSockets æå¡å¨ç«¯ç®åå®ç°
// çå¬å®¢æ·ç«¯çè¿æ¥è¯·æ± wsServer.on('connect', function(connection) { function sendCallback(err) { if (err) console.error("send() error: " + err); } // çå¬å®¢æ·ç«¯åéæ°æ®çè¯·æ± connection.on('message', function(message) { if (message.type === 'utf8') {// åºå«å®¢æ·ç«¯åè¿æ¥çæ°æ®æ¯ææ¬è¿æ¯äºè¿å¶ç±»å connection.sendUTF( "Server:Get message:<br/>"+message.utf8Data, sendCallback ); } else if (message.type === 'binary') { connection.sendBytes(message.binaryData, sendCallback); } }); connection.on('close', function(reasonCode, description) { }); });
å¾ 4. ç¹å» Connect æé®
å¾ 5. è¾å ¥å 容ï¼åå» Send Message æé®
Server-Sent Events
Server-Sent Events ç®ä»
HTML5 Server-Sent äºä»¶æ¨¡åå 许æ¨ä»æå¡å¨ push 宿¶æ°æ®å°æµè§å¨ãæ¬ææä»¬å°ä»ç»å©ç¨ Eventsource 对象å¤çä¸é¡µé¢é´çæ¥æ¶ååéæ°æ®ãå¨å®¢æ·ç«¯ï¼æä»¬ä½¿ç¨ HTML5+JavaScriptï¼æå¡ç«¯ä½¿ç¨ Javaãå¨ç°åç Ajax 模å¼ä¸ï¼web 页é¢ä¼æç»ä¸æå°è¯·æ±æå¡å¨ä¼ è¾æ°æ°æ®ï¼ç±å®¢æ·ç«¯è´è´£è¯·æ±æ°æ®ãè卿å¡ç«¯å鿍¡å¼ä¸ï¼æ éå¨å®¢æ·ç«¯ä»£ç 䏿§è¡è¿ç»çæ°æ®è¯·æ±ï¼èæ¯ç±æå¡ç«¯ push æ¨éæ´æ°ã䏿¦æ¨å¨é¡µé¢ä¸åå§åäº Server-Sent äºä»¶ï¼æå¡ç«¯èæ¬å°æç»å°åéæ´æ°ã客æ·ç«¯ JavaScript 代ç 䏿¦æ¥æ¶å°æ´æ°å°±å°æ°çæ°æ®åå ¥é¡µé¢ä¸å±ç¤ºåºæ¥ã
å¨ Server-Sent Events ä¸ä½¿ç¨ onmessage
Server-Sent Events å WebSockets æç¸åä¹å¤ï¼WebSockets å®ç°äºæå¡å¨ç«¯ä»¥å客æ·ç«¯çååéä¿¡åè½ï¼è Server-Sent Events åä» æ¯ææå¡å¨ç«¯å°å®¢æ·ç«¯çååéä¿¡ï¼èä¸ Server-Sent Events åæ ·éè¦æå¡å¨ç«¯çå®ç°ï¼æ¬æå°ä½¿ç¨åºäº Java ç Servlet ææ¯å®ç°æå¡å¨ç«¯ãå ³äºæå¡å¨ç«¯å客æ·ç«¯åæ°æ®çæ ¼å¼ï¼å¯ä»¥åè W3C å ³äº Server-Sent Events çè§èææ¡£ Server-Sent Eventsãç±äºæ¯æå¡å¨ç«¯å°å®¢æ·ç«¯çååéä¿¡ï¼æä»¥å¨ Server-Sent Events 䏿²¡æ postMessage æ¹æ³ã
é¦å ï¼å¨å®¢æ·ç«¯éè¿ JavaScript 代ç new ä¸ä¸ª EventSource å®ä¾åºæ¥ï¼åæ°æ¯å®ç° EventSource æå¡å¨ç«¯ URL å°åãç¶åå¨è¿ä¸ªå®ä¾ä¸çå¬ onmessage äºä»¶æ¥æ¶æå¡å¨ç«¯åéè¿æ¥çæ°æ®ã
æ¸ å 11. å建 EventSource 对象ï¼å¹¶çå¬ onmessage äºä»¶
if (!!window.EventSource) { // å建 EventSource å®ä¾ï¼ä¼ å ¥ server å°å var source = new EventSource('/TestHTML5/ServerSentEvent'); } else { console.log("Your browser doesn't support server-sent event"); } // çå¬ message äºä»¶ï¼çå¾ æ¥æ¶æå¡å¨ç«¯åéè¿æ¥çæ°æ® source.addEventListener('message', function(event) { //event 忰䏿 data 屿§ï¼å°±æ¯æå¡å¨åéè¿æ¥çæ°æ® console.log(event.data); }, false); //EventSource è¿æä¾äº onopen 以å onerror äºä»¶ source.addEventListener('open', function(event) { }, false); source.addEventListener('error', function(event) { if (event.readyState == EventSource.CLOSED) { } }, false);
æå¡å¨ç«¯ï¼å¨ Java è¯è¨å®ç°ç Servlet doGet æ¹æ³ä¸ä½¿ç¨ response 对象å客æ·ç«¯åæ°æ®
æ¸ å 10. æå¡å¨ç«¯ç®åå®ç°
// è¿éå¿ é¡»è®¾ç½® Content-Type 为 text/event-stream response.setHeader("Content-Type", "text/event-stream"); response.setHeader("Cache-Control", "no-cache"); response.setCharacterEncoding ("UTF-8"); String id = new Date().toString(); response.getWriter().println("id:"+id); // å客æ·ç«¯åä¸¤è¡æ°æ® response.getWriter().println("data:server-sent event is working."); response.getWriter().println("data:test server-sent event multi-line data"); response.getWriter().println(); response.getWriter().flush();
å¾ 6. Server-Sent Events è¿è¡ç»æ
ç»æè¯
æ¬æè¯¦ç»ä»ç»äº postMessageï¼sendï¼å onmessage API å¨å®¢æ·ç«¯çåºç¨æ åµï¼å¯ä»¥çå°å¨ä¸åçåºæ¯ä¸è¿ä¸¤ä¸ªæ¹æ³çåºç¨æ¨¡å¼é½æ¯ç±»ä¼¼çãpostMessage çä½ç¨å°±æ¯ä¼ éæ°æ®ï¼è onmessage çä½ç¨å°±æ¯æ¥æ¶æ°æ®ãææ¡æ¤ç» API 对以åå¼å HTML 5 åºç¨ç¨åºå°ä¼ææå¸®å©ãæ¬æ Web Workersï¼Cross-document messagingï¼WebSockets ç代ç å¨ Firefox 14 ä¸éè¿æµè¯ï¼Server-Sent Events ç代ç å¨ Chrome 16 ä¸éè¿æµè¯ã