亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

WebWorker與WebSocket實(shí)現(xiàn)前端消息總線

stefan / 1674人閱讀

摘要:讓端與服務(wù)端維持一個(gè)有效的長(zhǎng)連接,實(shí)現(xiàn)服務(wù)端主動(dòng)推送數(shù)據(jù)。不同是實(shí)現(xiàn)了服務(wù)端與客戶端的全雙工通訊。在未出現(xiàn)之前,要是實(shí)現(xiàn)一個(gè)信息推送的功能,通過(guò)來(lái)實(shí)現(xiàn)唯一方案就是輪訓(xùn),輪訓(xùn)分長(zhǎng)短,各有弊端。

Web Worker讓JS有了多線程的能力,可以將復(fù)雜耗時(shí)的操作都交付給Worker線程處理。WebSocket讓web端與服務(wù)端維持一個(gè)有效的長(zhǎng)連接,實(shí)現(xiàn)服務(wù)端主動(dòng)推送數(shù)據(jù)。將二者一結(jié)合,業(yè)務(wù)系統(tǒng)信息流轉(zhuǎn)通知功能完全就可以剝離出來(lái)。

架構(gòu)圖

JS Worker

Worker工作在一個(gè)專用的作用域DedicatedWorkerGlobalScope,在這個(gè)作用域中,不能直接操作DOM節(jié)點(diǎn),不能使用Window對(duì)象的默認(rèn)方法和屬性。不過(guò)對(duì)于網(wǎng)絡(luò)的訪問(wèn)是完全沒有問(wèn)題的。具體能使用那些對(duì)象和方法請(qǐng)點(diǎn)擊這里查看

從上圖中可明顯的看出,Worker在當(dāng)前架構(gòu)中實(shí)現(xiàn)一個(gè)橋梁的左右,上連接socket端中的數(shù)據(jù),下負(fù)責(zé)分發(fā)socket中的數(shù)據(jù)。此處我們先了解下Worker本身的功能實(shí)現(xiàn)。

主線程與Worker線程通過(guò)方法postMessage相互傳遞信息

主線程與Worker線程通過(guò)事件onmessage接收相互傳遞的消息

Worker中引入第三方j(luò)s使用方法importScripts([url,])

主線程調(diào)用worker.terminate()結(jié)束線程

Worker線程通過(guò)調(diào)用this.close()結(jié)束自身線程

新建一個(gè)webworker.js文件,并在其中編寫如下代碼

//author:herbert qq:464884492
onmessage = function (event) {
    if (event.data.code) {
        var code = event.data.code.toLowerCase();
        switch (code) {
            case "init":
                var userId = event.data.loggedUserId;
                var sessionId = event.data.sessionid;
                if (!sessionId) {
                    this.close();
                    return;
                }
                postMessage({ code: "codeone", msg: "你好,組件1" });
                postMessage({ code: "codetwo", msg: "你好,組件2" });
                break;
            default:
                break;
        }
    }
}
注意:在 onmessage 前不能加var否則在IE下會(huì)接收不了消息。IE真是讓人充滿挫敗感的瀏覽器

新建一個(gè)index.html頁(yè)面,在script塊中編寫以下代碼,實(shí)現(xiàn)與webworker.js通訊

//author:herbert qq:464884492
var work = new Worker("webworker.js")
    , textone = document.querySelector("#textone")
    , textTwo = document.querySelector("#texttwo")
      textAll = document.querySelector("#textAll");

work.onmessage = function (event) {
    var data = event.data;
    if (!!data.code) {
        switch (data.code) {
            case "close":
                work.terminate();
            case "codeone":
                textone.value = textone.value + JSON.stringify(data) + "
";
                textAll.value = textAll.value + JSON.stringify(data) + "
";
                break;
            case "codetwo":
                textTwo.value = textTwo.value + JSON.stringify(data) + "
";
                textAll.value = textAll.value + JSON.stringify(data) + "
";
                break;
            default:
                textAll.value = textAll.value + JSON.stringify(data) + "
";
        }
    }
};
work.postMessage({
    code: "init",
    loggedUserId: "demo",
    sessionid: "demo"
});
JS WebSocket

WebSocket和Http一樣都是基于Tcp協(xié)議。不同是WebSocket實(shí)現(xiàn)了服務(wù)端與客戶端的全雙工通訊。在Websocket未出現(xiàn)之前,要是實(shí)現(xiàn)一個(gè)信息推送的功能,通過(guò)http來(lái)實(shí)現(xiàn)唯一方案就是輪訓(xùn),輪訓(xùn)分長(zhǎng)短,各有弊端?,F(xiàn)在WebSocket一出現(xiàn),一切都好辦了。

接下來(lái)我們開始建立一個(gè)WebSocket連接

方法中的root表示當(dāng)前作用域,在主線程是root=window,在WebWorker線程root=DedicatedWorkerGlobalScope
    //author:herbert qq:464884492
    var root = this,socket =null;
    function connect(wsurl) {
        if ("WebSocket" in root) {
            socket = new WebSocket(wsurl);
        } else if ("MozWebSocket" in root) {
            socket = new MozWebSocket(wsurl);
        } else {
            alert("您的瀏覽器版本過(guò)低,將不能接收系統(tǒng)消息");
        }
    }

wsurl格式為 ws: 或者 wss:,后者表示SSL加密傳輸。實(shí)際地址如: ws://localhost:8090/demo/demowebsocket
接下來(lái),我們需要為socket處理事件,負(fù)責(zé)接收服務(wù)端推送的消息

   //author:herbert qq:464884492
   function onOpen() {
        postMessage({ code: "openConnect" });
    }
    function onClose() {
        postMessage({ code: "closewsconnect" });
    }
    function onMessaage(event) {
        postMessage(JSON.parse(event.data));
    }
    function onError(event) {
        socket = null;
        if (event.target.readyState == 3) {
            //斷線重連
            setTimeout(function () {
                connect(event.target.url);
                initMessageEvent();
            }, 1000);
        }
    }
    function sendMessage(msg) {
        if (socket == null) return;
        socket.send(msg);
    }
 function initMessageEvent() {
        socket.onopen = onOpen; //socket連接成功處理事件
        socket.onclose = onClose; //socket連接關(guān)閉處理事件
        socket.onmessage = onMessaage; //socket接收到新消息
        socket.onerror = onError; //soket錯(cuò)誤處理事件
    }
JAVA WebSocket

Tomcat7x已經(jīng)實(shí)現(xiàn)了標(biāo)準(zhǔn)WebScoket接口,在項(xiàng)目中只需要編寫一個(gè)普通的實(shí)體bean配置注解就可以實(shí)現(xiàn)一個(gè)標(biāo)準(zhǔn)的WebSocket Api。開發(fā)中主要使用一些注解

@ServerEndpoint 設(shè)置WebSocket連接地址,以及url參數(shù)
如: @ServerEndpoint(value = "/demowebsocket/{userId}/{sessionId}"),其中{userId}、{sessionId} 為pathParam可以在onOpen函數(shù)中通過(guò)函數(shù)參數(shù) @PathParam 獲取

@PathParam 獲取URL地址上對(duì)應(yīng)的注解參數(shù)

@OnOpen 建立連接注解

@OnClose 關(guān)閉連接注解

@OnMessage 接收消息注解

@OnError 錯(cuò)誤注解

被注解約束的函數(shù)都可以任意選擇需要的參數(shù),可選擇的參數(shù)有 Session、EndpointConfig 以及 @PathParam, 服務(wù)端Bean代碼如下

//author:herbert qq:464884492
@ServerEndpoint(value = "/demowebsocket/{userId}/{sessionId}")
public class DemoWebSokcet {
    private static final Set connections = new CopyOnWriteArraySet();
    private Session session;
    public DemoWebSokcet() {
    }

    @OnOpen
    public void openConnection(Session session, EndpointConfig conf,
            @PathParam("userId") String userId,
            @PathParam("sessionId") String sessionId) {
        this.session = session;
        connections.add(this);
        JSONObject jo = new JSONObject();
        jo.put("code", "newuser");
        jo.put("userid", userId);
        jo.put("sessionid", sessionId);
        jo.put("msg", "server:新連接用戶");
        sendMessage(jo);

        // 測(cè)試 代碼
        JSONObject jo1 = new JSONObject();
        jo1.put("code", "codeone");
        jo1.put("userid", userId);
        jo1.put("sessionid", sessionId);
        jo1.put("msg", "Server:組件1你好");
        sendMessage(jo1);

        JSONObject jo2 = new JSONObject();
        jo2.put("code", "codetwo");
        jo2.put("userid", userId);
        jo2.put("sessionid", sessionId);
        jo2.put("msg", "server:組件2你好");
        sendMessage(jo2);
    }

    @OnClose
    public void closeConnection(@PathParam("userId") String userId,
            @PathParam("sessionId") String sessionId) {
        connections.remove(this);
        JSONObject jo = new JSONObject();
        jo.put("code", "connectionClose");
        jo.put("userid", userId);
        jo.put("sessionid", sessionId);
        jo.put("msg", "server:連接關(guān)閉");
        sendMessage(jo);
    }

    // 處理文本消息
    @OnMessage
    public void handleTextMsg(Session session, String message,
            @PathParam("userId") String userId,
            @PathParam("sessionId") String sessionId) {
        System.out.println("userId=>" + userId + " sessionId=>" + sessionId);
        // 原樣轉(zhuǎn)發(fā)客戶端消息
        sendMessage(JSONObject.parseObject(message));
    }

    // 處理二進(jìn)制消息
    @OnMessage
    public void handleBinaryMsg(Session session, ByteBuffer msg,
            @PathParam("userId") String userId,
            @PathParam("sessionId") String sessionId) {

    }

    // 處理pong消息
    @OnMessage
    public void handlePongMsg(Session session, PongMessage msg,
            @PathParam("userId") String userId,
            @PathParam("sessionId") String sessionId) {
        JSONObject jo = new JSONObject();
        jo.put("code", "pong");
        jo.put("userid", userId);
        jo.put("sessionid", sessionId);
        jo.put("msg", msg.getApplicationData().toString());
        sendMessage(jo);
    }

    @OnError
    public void onError(Throwable t, @PathParam("userId") String userId,
            @PathParam("sessionId") String sessionId) throws Throwable {
        JSONObject jo = new JSONObject();
        jo.put("code", "servererror");
        jo.put("userid", userId);
        jo.put("sessionid", userId);
        jo.put("msg", t.getMessage());
        sendMessage(jo);
    }

    private static void sendMessage(JSONObject msg) {
        for (DemoWebSokcet client : connections) {
            try {
                synchronized (client) {
                    client.session.getBasicRemote()
                            .sendText(msg.toJSONString());
                }
            } catch (IOException e) {
                JSONObject jo = new JSONObject();
                jo.put("code", "servererror");
                jo.put("userid",
                        client.session.getPathParameters().get("userid"));
                jo.put("sessionid",
                        client.session.getPathParameters().get("sessionid"));
                connections.remove(client);
                try {
                    client.session.close();
                } catch (IOException e1) {
                }

                jo.put("msg", "server:發(fā)送消息出現(xiàn)異常,連接已關(guān)閉" + e.getMessage());
                sendMessage(jo);
            }
        }
    }
}

在測(cè)試代碼編寫過(guò)程中,通過(guò)pom方式引入javax.websocket-api,啟動(dòng)后始終出現(xiàn) Error during WebSocket handshake: Unexpected response code: 404連接錯(cuò)誤,后來(lái)通過(guò)直接件tomcat/bin下對(duì)應(yīng)的tomcat實(shí)現(xiàn)的jar復(fù)制到webapp對(duì)應(yīng)的bin文件夾下解決問(wèn)題。

Demo預(yù)覽

總結(jié)

篇幅比較長(zhǎng),讀到這里也不容易!WebWorker和WebSocket我也是第一次將二者結(jié)合起來(lái)。感覺現(xiàn)在javascript功能真的是越來(lái)越豐富了。demo地址,還有一點(diǎn)感悟,對(duì)于開發(fā)中的新知識(shí)點(diǎn),首先你得學(xué)會(huì)怎么用,其次在通過(guò)閱讀源碼,以及理論知識(shí)讓你使用的更順利,甚至改變它。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/76672.html

相關(guān)文章

  • WebWorkerWebSocket實(shí)現(xiàn)前端消息總線

    摘要:讓端與服務(wù)端維持一個(gè)有效的長(zhǎng)連接,實(shí)現(xiàn)服務(wù)端主動(dòng)推送數(shù)據(jù)。不同是實(shí)現(xiàn)了服務(wù)端與客戶端的全雙工通訊。在未出現(xiàn)之前,要是實(shí)現(xiàn)一個(gè)信息推送的功能,通過(guò)來(lái)實(shí)現(xiàn)唯一方案就是輪訓(xùn),輪訓(xùn)分長(zhǎng)短,各有弊端。 Web Worker讓JS有了多線程的能力,可以將復(fù)雜耗時(shí)的操作都交付給Worker線程處理。WebSocket讓web端與服務(wù)端維持一個(gè)有效的長(zhǎng)連接,實(shí)現(xiàn)服務(wù)端主動(dòng)推送數(shù)據(jù)。將二者一結(jié)合,業(yè)務(wù)系...

    Pines_Cheng 評(píng)論0 收藏0
  • 實(shí)現(xiàn)瀏覽器內(nèi)多個(gè)標(biāo)簽頁(yè)之間的通信

    摘要:實(shí)現(xiàn)瀏覽器內(nèi)多個(gè)標(biāo)簽頁(yè)之間的通信第一種方式協(xié)議首先我們得了解是什么它是一種網(wǎng)絡(luò)通信協(xié)議為什么會(huì)用到因?yàn)橛腥毕?,通信只可以由客戶端發(fā)起,服務(wù)器無(wú)法主動(dòng)向客戶端發(fā)送消息。然后還有種共享,這種是可以多個(gè)標(biāo)簽頁(yè)共同使用的。 實(shí)現(xiàn)瀏覽器內(nèi)多個(gè)標(biāo)簽頁(yè)之間的通信 第一種方式:websocket協(xié)議.1.首先我們得了解websocket是什么?它是一種網(wǎng)絡(luò)通信協(xié)議2.為什么會(huì)用到websocket?因...

    Freeman 評(píng)論0 收藏0
  • 實(shí)現(xiàn)瀏覽器內(nèi)多個(gè)標(biāo)簽頁(yè)之間的通信

    摘要:實(shí)現(xiàn)瀏覽器內(nèi)多個(gè)標(biāo)簽頁(yè)之間的通信第一種方式協(xié)議首先我們得了解是什么它是一種網(wǎng)絡(luò)通信協(xié)議為什么會(huì)用到因?yàn)橛腥毕?,通信只可以由客戶端發(fā)起,服務(wù)器無(wú)法主動(dòng)向客戶端發(fā)送消息。然后還有種共享,這種是可以多個(gè)標(biāo)簽頁(yè)共同使用的。 實(shí)現(xiàn)瀏覽器內(nèi)多個(gè)標(biāo)簽頁(yè)之間的通信 第一種方式:websocket協(xié)議.1.首先我們得了解websocket是什么?它是一種網(wǎng)絡(luò)通信協(xié)議2.為什么會(huì)用到websocket?因...

    Enlightenment 評(píng)論0 收藏0
  • 實(shí)現(xiàn)瀏覽器內(nèi)多個(gè)標(biāo)簽頁(yè)之間的通信

    摘要:實(shí)現(xiàn)瀏覽器內(nèi)多個(gè)標(biāo)簽頁(yè)之間的通信第一種方式協(xié)議首先我們得了解是什么它是一種網(wǎng)絡(luò)通信協(xié)議為什么會(huì)用到因?yàn)橛腥毕荩ㄐ胖豢梢杂煽蛻舳税l(fā)起,服務(wù)器無(wú)法主動(dòng)向客戶端發(fā)送消息。然后還有種共享,這種是可以多個(gè)標(biāo)簽頁(yè)共同使用的。 實(shí)現(xiàn)瀏覽器內(nèi)多個(gè)標(biāo)簽頁(yè)之間的通信 第一種方式:websocket協(xié)議.1.首先我們得了解websocket是什么?它是一種網(wǎng)絡(luò)通信協(xié)議2.為什么會(huì)用到websocket?因...

    lcodecorex 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<