日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

webSocket通信js封裝

 hncdman 2023-02-03 發(fā)布于湖南

webSocket通信封裝

一. js使用WebSocket介紹

二. webSocket js封裝使用

三. js封裝代碼

一. js使用WebSocket介紹

1. 創(chuàng)建WebSocket實(shí)例

url:url之前需添加ws://(未加密)或wss://(已加密),類似http://、https://

protocol:與服務(wù)端定義的協(xié)議名稱相同,協(xié)議的參數(shù)例如XMPP(Extensible Messaging and Presence Protocol)、SOAP(Simple Object Access Protocol)或者自定義協(xié)議

var ws = new WebSocket('ws://url');

var ws1 = new WebSocket('ws://url', 'myprotocol');

var ws2 = new WebSocket('ws://url', ['protocol_1','protovol_2']));

1

2

3

2.屬性

①readyState屬性:WebSocket當(dāng)前連接狀態(tài)

屬性值 屬性常量 描述

0 CONNECTING 正在與服務(wù)端建立WebSocket連接,還沒有連接成功

1 OPEN 連接成功并打開,可以發(fā)送消息

2 CLOSING 進(jìn)行關(guān)閉連接的操作,且尚未關(guān)閉

3 CLOSE 連接已關(guān)閉或不能打開

通過 ws.readyState屬性查看當(dāng)前連接狀態(tài)

alert('ws連接狀態(tài):' + ws.readyState);

1

②bufferedAmount:檢查傳輸數(shù)據(jù)的大小,當(dāng)客戶端傳輸大量數(shù)據(jù)時(shí)使用避免網(wǎng)絡(luò)飽和

③protocol:在構(gòu)造函數(shù)中使用,protocol參數(shù)讓服務(wù)端知道客戶端使用的WebSocket協(xié)議。而WebSocket對(duì)象的這個(gè)屬性就是指的最終服務(wù)端確定下來的協(xié)議名稱,可以為空

3. 方法

①發(fā)送數(shù)據(jù):send()

②關(guān)閉連接:closed()

//發(fā)送數(shù)據(jù)

var message = {

id: 1,

title: '發(fā)送ws數(shù)據(jù)'

}

ws.send(JSON.stringify(message));    // 復(fù)雜的數(shù)據(jù)結(jié)構(gòu)要先進(jìn)行序列化

//關(guān)閉連接

ws.close()


4. 事件

WebSocket API是純事件驅(qū)動(dòng),建立連接之后,可自動(dòng)發(fā)送狀態(tài)改變的數(shù)據(jù)和通知

事件值 描述

onopen 當(dāng)建立websocket連接時(shí)觸發(fā),只觸發(fā)一次

onerror 當(dāng)連接出現(xiàn)錯(cuò)誤時(shí)觸發(fā)-因?yàn)楫?dāng)觸發(fā)了onerror之后連接就會(huì)觸發(fā)關(guān)閉事件

onmessage 當(dāng)服務(wù)端發(fā)送數(shù)據(jù)時(shí)觸發(fā),可多次觸發(fā),頁面數(shù)據(jù)展示處理模塊–實(shí)現(xiàn)輪詢

onclose 當(dāng)websocket連接關(guān)閉時(shí)觸發(fā),只觸發(fā)一次

使用示例

var ws = new WebSocket('ws://url');

// 獲取連接狀態(tài)

console.log('ws連接狀態(tài):' + ws.readyState);

//監(jiān)聽是否連接成功

ws.onopen = function () {

    console.log('ws連接狀態(tài):' + ws.readyState);

    //連接成功則發(fā)送一個(gè)數(shù)據(jù)

    ws.send('test1');

}

// 接聽服務(wù)器發(fā)回的信息并處理展示

ws.onmessage = function (data) {

    console.log('接收到來自服務(wù)器的消息:');

    console.log(data);

    //完成通信后關(guān)閉WebSocket連接

    ws.close();

}

// 監(jiān)聽連接關(guān)閉事件

ws.onclose = function () {

    // 監(jiān)聽整個(gè)過程中websocket的狀態(tài)

    console.log('ws連接狀態(tài):' + ws.readyState);

}

// 監(jiān)聽并處理error事件

ws.onerror = function (error) {

    console.log(error);

}


二. webSocket js封裝使用

創(chuàng)建一個(gè)js文件, 代碼在下, 最后將方法暴露出去, 使用的時(shí)候可以直接引用文件中的方法 調(diào)用, 或者 將該js文件掛載在vue的prototype中

直接引用文件 方法 調(diào)用

import {createWebSocket} from '@/utils/socket’

createWebSocket()

掛載在vue的prototype中

3. 整個(gè)項(xiàng)目只有一條webSocket通信:

① 在登錄后即可創(chuàng)建webSocket通信, 接受的數(shù)據(jù)中可定義一個(gè)參數(shù), 該參數(shù)來控制是 做什么功能

例如這里 :

“webSocket_device_transport” 是某一個(gè)界面需要實(shí)時(shí)添加的一些數(shù)據(jù)

“webSocket_device_alarm” 是一個(gè)全局提示彈框, 需要添加的數(shù)據(jù)

② 創(chuàng)建了 new Map(); key和value 用來一一對(duì)應(yīng)發(fā)送和接受的數(shù)據(jù)

//思路

var globalCallback = new Map();  //創(chuàng)建 new Map()

globalCallback.set(key,callback);  //發(fā)送數(shù)據(jù)的時(shí)候, 要定義一個(gè)唯一的key 和后端返回的key是一一對(duì)應(yīng), 定義一個(gè)回調(diào)函數(shù)用來接收數(shù)據(jù)后處理數(shù)據(jù)

//例如上圖片中 接收的數(shù)據(jù) res.method == "webSocket_device_transport",  用sn作為唯一的標(biāo)識(shí)符, 

// 客戶端在發(fā)送數(shù)據(jù)時(shí) globalCallback.set("sn",resultFunc),  通過globalCallback存了一個(gè)key為"sn"的回調(diào)函數(shù),

// 然后通信接收的數(shù)據(jù)中 返回作為標(biāo)識(shí)符的"sn", 用來查找存的回調(diào)函數(shù), 然后處理數(shù)據(jù).  (因?yàn)樘幚頂?shù)據(jù)的方法可能有多種, 不唯一, 所以用回調(diào)函數(shù))

const callback = globalCallback.get(ret.sn)

callback(ret);


三. js封裝代碼

import { getToken} from '@/utils/auth'

var websock = null;

let rec; //斷線重連后,延遲5秒重新創(chuàng)建WebSocket連接  rec用來存儲(chǔ)延遲請(qǐng)求的代碼

let isConnect = false; //連接標(biāo)識(shí) 避免重復(fù)連接

let checkMsg = "heartbeat"; //心跳發(fā)送/返回的信息 服務(wù)器和客戶端收到的信息內(nèi)容如果如下 就識(shí)別為心跳信息 不要做業(yè)務(wù)處理

var globalCallback = new Map();

let createWebSocket = () => {

  try {

    initWebSocket(); //初始化websocket連接

  } catch (e) {

    console.log("嘗試創(chuàng)建連接失敗");

    reConnect(); //如果無法連接上webSocket 那么重新連接!可能會(huì)因?yàn)榉?wù)器重新部署,或者短暫斷網(wǎng)等導(dǎo)致無法創(chuàng)建連接

  }

};

//定義重連函數(shù)

let reConnect = () => {

  console.log("嘗試重新連接");

  if (isConnect) return; //如果已經(jīng)連上就不在重連了

  rec && clearTimeout(rec);

  rec = setTimeout(function () { // 延遲5秒重連  避免過多次過頻繁請(qǐng)求重連

    createWebSocket();

  }, 5000);

};

//設(shè)置關(guān)閉連接

let closeWebSocket = () => {

  websock.close();

};

//心跳設(shè)置

var heartCheck = {

  timeout: 20000, //每段時(shí)間發(fā)送一次心跳包 這里設(shè)置為20s

  timeoutObj: null, //延時(shí)發(fā)送消息對(duì)象(啟動(dòng)心跳新建這個(gè)對(duì)象,收到消息后重置對(duì)象)

  start: function () {

    this.timeoutObj = setInterval(function () {

      console.log("hearting ....")

      if (isConnect) websock.send(checkMsg);

    }, this.timeout);

  },

  reset: function () {

    clearInterval(this.timeoutObj)

    this.start();

  },

  stop: function (){

    clearInterval(this.timeoutObj)

  }

};

// 初始化websocket

function initWebSocket() {

  // ws地址

  // const wsUri = "ws://10.27.100.151:5000/occpws/customWebSocket";

 const wsUri = "wss://cloudiot.notioni.com/ws/occpws/customWebSocket";

  websock = new WebSocket(wsUri,getToken())

  websock.onmessage = function (e) {

    websocketonmessage(e)

  }

  websock.onclose = function (e) {

    websocketclose(e)

  }

  websock.onopen = function () {

    websocketOpen()

    heartCheck.start();

  }

  // 連接發(fā)生錯(cuò)誤的回調(diào)方法

  websock.onerror = function () {

    console.log('WebSocket連接發(fā)生錯(cuò)誤')

    isConnect = false; //連接斷開修改標(biāo)識(shí)

    reConnect(); //連接錯(cuò)誤 需要重連

  }

}

// 實(shí)際調(diào)用的方法

function sendSock(agentData, callback, key) {

  if (!websock){

    initWebSocket()

  }

  globalCallback.set(key,callback)

  if (websock.readyState === websock.OPEN) {

    // 若是ws開啟狀態(tài)

    websocketsend(agentData)

  } else if (websock.readyState === websock.CONNECTING) {

    // 若是 正在開啟狀態(tài),則等待1s后重新調(diào)用

    setTimeout(function () {

      sendSock(agentData, callback,key)

    }, 2000)

  } else {

    // 若未開啟 ,則等待1s后重新調(diào)用

    setTimeout(function () {

      sendSock(agentData, callback,key)

    }, 2000)

  }

}

function getSock(key,callback) {

  globalCallback.set(key,callback)

}

// 數(shù)據(jù)接收

function websocketonmessage(e) {

  let ret = JSON.parse(decodeUnicode(e.data))

  if (!ret) {

    heartCheck.reset()

  } else {

    if (ret.msg === "websocket connect success") { 

    } else {

      if (ret.method === "webSocket_device_transport"){

        const callback = globalCallback.get(ret.sn)

        if (callback && typeof callback === "function")

        callback(ret);

      }else if(ret.method === "webSocket_device_alarm"){ 

        const callback = globalCallback.get('deviceAlert')

        if (callback && typeof callback === "function")

        callback(ret);

      }

    }

  }

  // globalCallback(JSON.parse(e.data))

  function decodeUnicode(str) {

    str = str.replace(/\\/g, "%");

    //轉(zhuǎn)換中文

    str = unescape(str);

    //將其他受影響的轉(zhuǎn)換回原來

    str = str.replace(/%/g, "\\");

    //對(duì)網(wǎng)址的鏈接進(jìn)行處理

    str = str.replace(/\\/g, "");

    return str;

  }

}

// 數(shù)據(jù)發(fā)送

function websocketsend(agentData) {

  console.log("數(shù)據(jù)發(fā)送",JSON.stringify(agentData))

  websock.send(JSON.stringify(agentData))

}

// 關(guān)閉

function websocketclose(e) {

  console.log(e)

  isConnect = false ; //斷開后修改標(biāo)識(shí)

  heartCheck.stop()

  console.log('connection closed (' + e.code + ')')

}

// 創(chuàng)建 websocket 連接

function websocketOpen(e) {

  isConnect = true

  console.log('連接成功')

}

//登錄成功后再建立連接

//initWebSocket()

// 將方法暴露出去

export {

  sendSock,

  getSock,

  createWebSocket,

  closeWebSocket,

  initWebSocket

}

————————————————

版權(quán)聲明:本文為CSDN博主「Hello 阿凡達(dá)」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/qq_38746300/article/details/128675243

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多