前端日拱一卒D7 WEB即時通訊

2021-09-11 15:25:33 字數 3343 閱讀 6187

余為前端菜鳥,感姿勢水平匱乏,難觀前端之大局。遂決定循前端知識之脈絡,以興趣為引,輔以幾分堅持,望於己能解惑致知、於同道能助力一二,豈不美哉。

本系列**及文件均在 此處

最簡單的實現方式,由客戶端定時向服務端請求資料

簡單實現

// 設定定時器,每秒向伺服器請求資料

複製**

評價

最簡單,但是請求次數太多,每次都要建立連線,對伺服器壓力也很大,大部分時間資料是沒有更新的,浪費頻寬。

服務端接收客戶端請求後暫時掛起,等待資料更新,有資料更新則響應,否則等到達到服務端設定的時間限制後再響應。客戶端接收到響應後會再發出請求,重新建立連線,如此往復。

簡單實現

ajax = () => \n$`

// 重新建立連線

ajax()

}} xhr.send()

}window.onload = () =>

複製**

//

document.getelementbyid("sub").onclick = () => `)

}複製**

// 使用eventemitter進行事件監聽

const eventemitter = require('events').eventemitter

const messagebus = new eventemitter()

messagebus.setmaxlisteners(100)

if (ctx.request.url === '/test') )

})ctx.body = result

} // 接收到message,觸發事件

if (ctx.request.url === '/message')

})複製**

評價

減少了請求次數,但服務端掛起依然是資源浪費。輪詢與長輪詢都是服務被動型,都是由客戶端發起請求。

具體**見 github

sse(server-sent events)是h5新增的功能,允許服務端主動向客戶端推送資料。

簡單實現

// 客戶端會在連線失敗後預設重連

const source = new eventsource('/sse')

// 預設為message,這裡的test1為自定義

source.addeventlistener('test1', (res) => , false)

source.onopen = () =>

source.onerror = (err) =>

// source.close(); // 用於關閉連線

複製**

const readable = require('stream').readable

// 建立自定義流

function

rr() {}

rr.prototype = object.create(new readable());

rr.prototype._read = function (data) {}

if (ctx.request.url === '/sse') )

let stream = new rr()

let count = 1

stream.push(`event: test1\ndata: $)}\n\n`)

// 返回的訊息格式有要求,這裡返回流是因為koa特殊

// 如果不是流會呼叫res.end(buffer),結束http響應

ctx.body = stream

// 多次主動響應,共用乙個連線

const timer = setinterval(() => )}\n\n`)

if (count > 5)

ctx.body = stream

}, 2000)

}複製**

返回的訊息格式應包含這幾個字段

id: 1

// 事件id

event: test1 // 自定義事件,不設定則預設為message

data: // 資料

retry : 10000

// 重連時間

複製**

評價

與前兩者一樣基於http協議,相比於長輪詢,不需要客戶端後續請求,只需要維持乙個請求,後續服務端主動推送,且實現也比較簡單。

具體**見 github

websocket是有別於http的一種新協議,誕生已有十年之久。websocket握手階段採用http協議,沒有同源限制,識別符號為ws

簡單實現

// 原生寫法

const ws = new websocket('ws:')

ws.readystate 0 正在連線 1 已連線 2 正在關閉 3 已關閉

ws.onopen = (evt) =>

ws.onmessage = (evt) => `)

ws.close()

}// socket.io-client

// 服務端用的socket.io,客戶端不用相應的client會有問題

const ws = io('ws:');

ws.on('connect', (evt) => )

ws.on('message', (evt) => `)

ws.close()

});ws.on('disconnect', () => );

複製**

// with koa

const io = require('socket.io')(server)

io.on('connection', (socket) => );

});server.listen('5001')

複製**

評價

使用起來非常簡單,在單個tcp連線上實現客戶端和服務端之間的全雙工通訊,效能在幾者中最好,後續想寫聊天室玩的時候再來搞搞。

web即時通訊其實要解決的乙個是效能問題,乙個是效率問題。效能上像長輪詢和短輪詢都是比較差的,效率我理解體現在實時性和主動性上。長連線和websocket都可以實現服務端主動推送,websocket實現的是雙方你來我往的雙工通訊,更適用於即時通訊的場景。具體做這方面東西肯定會碰到一些坑的,這裡淺嘗輒止,以後有機會接觸再做深入。

雖發表於此,卻畢竟為一人之言,又是每日學有所得之筆記,內容未必詳實,看官老爺們還望海涵。

日拱一卒(一)

layer list 用來多個圖層堆疊顯示的 在drawable資料夾下建立乙個xml檔案。比如 background.xml 另外在layout檔案中指定background屬性這樣就會載入pic1和pic2這兩張。imageview android background drawable bac...

日拱一卒(十四)

git 初識 1.安裝 linux sudo apt get install git core 2.建立 倉庫 linux下開啟shell,windows開啟git bash 1 配置下身份 git config global user.name tony git config global use...

日拱一卒(三十)

迪公尺特法則 lod 如果兩個類不能彼此直接通訊,那麼這兩個類就不應到發生直接的作用。如果其中乙個類需要呼叫另一類的某乙個方法的話,可以通過第三方 這個呼叫。白話 android中intent類就是這個很好的例項,activity,service之間設計就是這樣的松耦合,他們不直接通訊,而是用int...