http://blog.csdn.net/zha_zi/article/details/41677033 HTML5 中 postMessage sendMessage 用法javascript
Html5對多線程的支持。在 HTML5 中提出了工做線程(Web Workers)的概念。用於解決頁面之間數據處理的多線程,加快數據處理。如同java中的Thread。css
Web Workers 的三大主要特徵: 可以長時間運行(響應),理想的啓動性能以及理想的內存消耗。html
Web Workers 容許開發人員編寫可以長時間運行而不被用戶所中斷的後臺程序,去執行事務或者邏輯,並同時保證頁面對用戶的及時響應。前端
Web Workers 爲 Web 前端網頁上的腳本提供了一種能在後臺進程中運行的方法。一旦它被建立,Web Workers 就能夠經過 postMessage 向任務池發送任務請求,執行完以後再經過 postMessage 返回消息給建立者指定的事件處理程序 ( 經過 onmessage 進行捕獲 )。Web Workers 進程可以在不影響用戶界面的狀況下處理任務,而且,它還可使用 XMLHttpRequest 來處理 I/O,但一般,後臺進程(包括 Web Workers 進程)不能對 DOM 進行操做。若是但願後臺程序處理的結果可以改變 DOM,只能經過返回消息給建立者的回調函數進行處理。java
主線程-----------------------------------------------------node
var worker = new Worker('***.js'); web
--僅能存放同域的處理數據用,或ajax調用數據用的js,子線程的js不能操做dom節點,由於子線程不能影響主線程對dom的操做。ajax
worker.postMessage(data); 經過postMessage方法來關聯主子線程。data爲任意值json
worker.terminate(); 終止workers,一旦終止則不能再使用,須要從新new workerwindows
worker.message(); 接收信息用,放入監控中則一直有效。
worker.error(); 對錯誤的處理
子線程--------------------------------------------------------
子線程中的js可操做範圍:
worker.js執行的上下文與主頁面html執行時的上下文並不相同,最頂層的對象並非window,而是WorkerGlobalScope。
所以window的alert方法在此js中不能用。WorkerGlobalScope的屬性方法:
一、self
咱們可使用 WorkerGlobalScope 的 self 屬性來或者這個對象自己的引用
二、location
location 屬性返回當線程被建立出來的時候與之關聯的 WorkerLocation 對象,它表示用於初始化這個工做線程的腳步資源的絕對 URL,即便頁面被屢次重定向後,這個 URL 資源位置也不會改變。
三、close
關閉當前線程,與terminate做用相似
四、importScripts
咱們能夠經過importScripts()方法經過url在worker中加載庫函數
五、XMLHttpRequest
有了它,才能發出Ajax請求
六、setTimeout/setInterval以及addEventListener/postMessage
1.能夠加載一個JS進行大量的複雜計算而不掛起主進程,並經過postMessage,onmessage進行通訊
2.能夠在worker中經過importScripts(url)加載另外的腳本文件
3.可使用 setTimeout(), clearTimeout(), setInterval(), and clearInterval()
4.可使用XMLHttpRequest來發送請求
5.能夠訪問navigator的部分屬性
侷限性:
1.不能跨域加載JS
2.worker內代碼不能訪問DOM
3.各個瀏覽器對Worker的實現不大一致,例如FF裏容許worker中建立新的worker,而Chrome中就不行
示例:
加載報錯「Uncaught DOMException: Failed to construct 'Worker': 」 --部分瀏覽器不容許本地加載外部文件,須要放在web容器中運行。
1 $(function($){ 2 if(typeof(window.Worker) != 'undefined'){ 3 var worker = new Worker('worker.js'); 4 worker.postMessage("主線程:請求處理數據------"); 5 worker.onmessage = function(e){ // 注意這裏message是小寫 6 console.log("---" + e.data); 7 } 8 worker.onerror = function(e){ 9 console.log("---" + e.message); 10 worker.terminate(); 11 } 12 worker.postMessage("主線程:請求處理數據------"); 13 } 14 console.log("我只是飄過。。。。。"); 15 });
1 /** 2 * worker.js 的上下文頂級對象爲WorkerGlobalScope,沒有document和windows對象。所以dom元素不能操做,windows的部分方法不能使用.注意保存的編碼格式 3 * DennyZhao 4 * Date:2017/9/22 5 */ 6 var self = this;
self.importScripts('script1.js'); //限定爲WorkerGlobalScope對象內容
7 self.onmessage = function(event){
8 //console.log("-----work);//這個不起做用不支持console
9 self.postMessage(" 開始處理主線程的任務。。。。。。" + event.data);
10 var a = event.data;
11 a += "處理過程¥¥";
12 self.postMessage("主線程的任務處理完畢........" + a);
13 self.close(); 14 }
結果:
我只是飄過。。。。。
--- 開始處理主線程的任務。。。。。。主線程:請求處理數據------
---主線程的任務處理完畢........主線程:請求處理數據------處理過程¥¥
H5推出的信息隊列調用,能夠解決兩個window之間的信息共享,iframe內外信息傳遞,本地調用遠端頁面到本地的跨域信息傳遞,方法調用等問題。
不過僅限於前臺web的頁面之間調用,還沒辦法解決跨域的前臺和後臺的調用,還需用Ajax的jsonP形式進行傳遞。
postMessage採用異步通訊的方式,所以能夠作頁面的js動做和渲染用。同時不影響別的代碼繼續執行,提升處理速度。
1.本地自身使用消息隊列的postMessage(若是同時執行在同一個window上,會由於渲染和js處理同時進行致使併發出錯)
1 window.addEventListener('message',function(e){ 2 console.log("event------" + e.data); 3 },false); 4 // postMessage 5 $(function($){ 6 function postMessages(){ 7 window.postMessage("12345","/"); 8 console.log("--45678----"); 9 } 10 postMessages(); 11 }); 12 13 14 結果:異步執行動做 15 --45678---- 16 event------12345
2. iframe中的內外交互
在windows/system32/driver/etc/host 下,修改127.0.0.1
127.0.0.1 test.com
127.0.0.1 test2.com
這樣就造成跨域請求,若是不跨域時,可不設置。(以上爲測試用)
1 <script type="text/javascript"> --父窗體 2 // postMessage 3 window.addEventListener("message", function(event){ 4 $("div").css("backgroundColor","#" + event.data); 5 }); 6 $(function($){ 7 //$("#myIframe")[0].contentWindow.postMessage("getMessage", "http://test2.com:8080"); 放此地方報錯,iframe的src還未裝載 8 $("button").click(function(){ 9 $("#myIframe")[0].contentWindow.postMessage("getMessage", "http://test2.com:8080"); //注意此處調用子url時須要iframe已經產生渲染完畢。 10 }); 11 12 13 }); 14 15 </script>
1 <script type="text/javascript"> --iFrame 2 var color= 50; 3 window.addEventListener("message", function(event){ 4 $('div').css("backgroundColor", "red"); 5 6 },false); 7 // postMessage 8 $(function($){ 9 10 $('div').click(function(){ 11 color = color + 100000; 12 $(this).css("backgroundColor", "#" + color); 13 window.top.postMessage(color, "http://test.com:8080"); 14 }); 15 16 }); 17 18 </script>
3. openWindow中使用
1 <script type="text/javascript"> 2 // postMessage 3 window.addEventListener("message", function(event){ 4 $("div").css("backgroundColor","#" + event.data); 5 }); 6 $(function($){ 7 //$("#myIframe")[0].contentWindow.postMessage("getMessage", "http://test2.com:8080"); 放此地方報錯,iframe的src還未裝載 8 $("button").click(function(){ 9 var child = window.open("http://test2.com:8080/webtest/worker/iFrame.html", "_blank"); 10 var my = setInterval(function(){ 11 if(child && !child.closed){ 12 child.postMessage("getMessage", "http://test2.com:8080"); //注意此處調用子url時須要window已經產生 13 clearInterval(my); 14 } 15 }, 200); 16 }); 17 18 19 }); 20 21 </script>
1 <script type="text/javascript"> 2 var color= 50; 3 window.addEventListener("message", function(event){ 4 $('div').css("backgroundColor", "red"); 5 6 },false); 7 // postMessage 8 $(function($){ 9 10 $('div').click(function(){ 11 color = color + 100000; 12 $(this).css("backgroundColor", "#" + color); 13 window.opener.postMessage(color, "http://test.com:8080"); 14 }); 15 16 }); 17 18 </script>
在 Web 應用中,HTTP 協議決定了客戶端和服務端鏈接是短鏈接,即客戶端 Request,服務端 Response,鏈接斷開。要想實現客戶端和服務端實時通訊,只能經過客戶端輪詢來實現。服務端推送數據也並非字面上意思上的直接推,其實仍是客戶端本身取。WebSockets 是 HTML5 規範新引入的功能,用於解決瀏覽器與後臺服務器雙向通信的問題,使用 WebSockets 技術,後臺能夠隨時向前端推送消息,以保證先後臺狀態統一。
WebSockets 服務器端有 jetty 提供的基於 Java 的實現,有 WebSocket-Node 基於 node.js 的實現。
1.選用nodeJs做爲服務器端應用(參見nodejs 建立webSocket)
1 var WebServer = require('ws').Server; 2 var wss = new WebServer({port:3500}); 3 wss.on('connection', function(ws){ 4 console.log('建立鏈接成功!'); 5 ws.on('message', function(msg){ 6 console.log(msg); 7 }); 8 setInterval(function(){ 9 ws.send(Math.random() * 10000); 10 },1000); 11 });
前臺發送信息到後臺: 1 <script type="text/javascript"> 2 $(function($){
3 var server = { 4 ws : {}, 5 connection : function(){ 6 this.ws = new WebSocket("ws://test.com:3500/"); 7 this.recieve(); 8 this.open(); 9 this.ws.onerror = function(error, data){ 10 console.log("error : " + error); 11 server.ws.close(); 12 } 13 }, 14 send : function(_msg){ 15 server.ws.send(_msg); 16 }, 17 recieve : function(){ 18 server.ws.onmessage = function(event){ 19 if(event.data){ 20 $("<div>").text(event.data).appendTo('body'); 21 } 22 } 23 }, 24 close : function(){ 25 server.ws = null; 26 }, 27 open : function(){ 28 server.ws.onopen= function(){
35 console.log("webSocket已經連接.......");
36 server.ws.send('webSocket已經建立');
47 } 48 }; 49 // 鏈接 50 server.connection(); 51 var i = 0; 52 var myInterval = setInterval(function(){ 53 i = i + 1; 54 server.send('發送 ' + i + ': '); 55 if(server.ws.readyState != 1){ 56 clearInterval(myInterval); 57 } 58 }, 1000); 59 }); 60 61 </script>
結果:
1 C:\Users\Administrator\Desktop\test\nodeJs>node websocket 2 建立鏈接成功! 3 webSocket已經建立 4 發送 1: 5 發送 2: 6 發送 3: 7 發送 4: 8 發送 5: 9 發送 6: 10 發送 7: 11 發送 8: 12 發送 9: 13 發送 10: 14 發送 11: 15 發送 12: 16 發送 13: 17 發送 14: 18 發送 15: 19 發送 16: 20 發送 17: 21 22 頁面接收部分:----- 23 4848.977736803326 24 7762.762571534494 25 3343.602966652355 26 1073.4970072202343 27 8700.747665594601 28 2556.6261964728064 29 3065.183213127105 30 134.2700772638583 31 7319.230923541 32 3183.5101594279868 33 6892.64312993447 34 1412.415079333049 35 6946.477577338111 36 4111.868595940827 37 5996.174673001297 38 4171.965367213602 39 1790.7039601051533
HTML5 Server-Sent 事件模型容許您從服務器 push 實時數據到瀏覽器。與Web-Socket相比,Server-Sent Events 僅可由服務器向客戶端單方面推送信息,而不能有客戶端向服務端推送請求。好處是不用創建服務端的 WebSocket服務。
利用 Eventsource 對象處理與頁面間的接收和發送數據。在客戶端,咱們使用 HTML5+JavaScript,服務端使用 Java。在現存的 Ajax 模式中,web 頁面會持續不斷地請求服務器傳輸新數據,由客戶端負責請求數據。而在服務端發送模式下,無需在客戶端代碼中執行連續的數據請求,而是由服務端 push 推送更新。一旦您在頁面中初始化了 Server-Sent 事件,服務端腳本將持續地發送更新。客戶端 JavaScript 代碼一旦接收到更新就將新的數據寫入頁面中展現出來。使用基於 Java 的 Servlet 技術實現服務器端。
爲方便快捷,咱們使用nodejs做爲服務器端。
1 var http = require('http'); 2 const path = require('path'); 3 path.basename('index.html'); 4 var url = require('url'); 5 var fs = require('fs'); 6 var filehome = "./html"; 7 http.createServer(function(req,res){ 8 console.log(''); 9 // 文件系統 10 if(req.url.search(/\.html|\.js/i) > 0){ 11 filepath = filehome + req.url; 12 fs.readFile(filepath, function(error, data){ 13 if(error){ 14 res.writeHeader(404, {"Content-Type":"text/html;charset='utf-8'"}); 15 res.write('<h1>404錯誤</h1><p>你要找的頁面不存在</p>'); 16 res.end(); 17 }else{ 18 res.writeHeader(200, {"Content-Type":"text/html;charset='utf-8'"}); 19 res.write(data); 20 res.end(); 21 } 22 }); 23 return; 24 } 25 26 // 請求處理 27 var pathname = url.parse(req.url).pathname; 28 res.writeHeader(200, {"Content-Type":"text/event-stream"}); 29 if(pathname.search('/serverEvent') > -1){ 30 setInterval(function(){ 31 var date = new Date().getTime(); 32 var content = "data:" + date + "\n\n"; 33 res.write(content); 34 res.flushHeaders(); 35 //res.end(); 此處不能關閉,否則會中斷Server-Sent EVENT拋出error 36 }, 1000); 37 } 38 }).listen(3011, '127.0.0.1'); 39 40 console.log("啓動成功,請去http://127.0.0.1:3011 下嘗試。。。。");
客戶端:
1 $(function($){ 2 var source = new EventSource('http://127.0.0.1:3011/serverEvent'); 3 source.onmessage=function(event){ 4 $("<div>").text(event.data).appendTo('body'); 5 }; 6 source.onerror = function(error, event){ 7 $("<div>").text('Error is occur.....').appendTo('body'); 8 } 9 10 source.open=function(event){ 11 $("<div>").text("鏈接建立成功。。。。。").appendTo('body'); 12 }; 13 });