ajax轮询模拟websocket,Ajax轮询和SSE服务器推送数据与websocket模式的区别性学习
我們?cè)囅胍幌挛覀冏鰝€(gè)實(shí)時(shí)聊天的窗口有幾種方法?
在我們不刷新頁(yè)面并且可以試試更新頁(yè)面內(nèi)容的方法 你這時(shí)候是不是想到了ajax沒(méi)錯(cuò)確實(shí)可以
Ajax輪詢
什么是輪詢?顧名思義就是我輪著問(wèn)你,規(guī)定一個(gè)時(shí)間然后我就問(wèn)你 有新數(shù)據(jù)了嗎? 有新數(shù)據(jù)了嗎? 有新數(shù)據(jù)了嗎? 當(dāng)有新數(shù)據(jù)的時(shí)候就更新頁(yè)面。
但是性能會(huì)很差。。。
并且這是前臺(tái)操作的 后端只需要查詢數(shù)據(jù)庫(kù) 設(shè)置好路由即可
Node后端
簡(jiǎn)單的說(shuō)就是 后端設(shè)置一個(gè)路由然后進(jìn)行查詢數(shù)據(jù)獲取想要的數(shù)據(jù)的操作
const Koa = require("koa");
const static = require("koa-static");
const Router = require("koa-router");
const mysql2 = require("mysql2");
const koaBody = require("koa-body");
let app = new Koa();
app.use(static(__dirname+"/static"));
app.use(koaBody());
//連接數(shù)據(jù)庫(kù)
const connection = mysql2.createConnection({
host:"localhost",
user:"root",
password:"123",
database:"js04"
})
let router = new Router();
//訪問(wèn)此路由進(jìn)行獲取數(shù)據(jù)
router.get("/getData",async ctx=>{
let [rows] = await connection.promise().query("SELECT * FROM message");
ctx.body = rows;
})
app.use(router.routes());
app.listen(3000);
前端
前端我要訪問(wèn)這個(gè)路由然后獲取數(shù)據(jù) 而ajax 是不會(huì)刷新頁(yè)面的。
$.ajax({
//訪問(wèn)路由
url: "/getData",
success(res) {
//res 就是回的數(shù)據(jù)
console.log(res);
}
})
怎么進(jìn)行輪詢呢?
上面我們說(shuō)什么 規(guī)定一個(gè)時(shí)間然后 每隔多長(zhǎng)時(shí)間進(jìn)行詢問(wèn)
那么這不就是定時(shí)器嗎
我們將上面的ajax進(jìn)行封裝成方法里面 然后用定時(shí)器進(jìn)行 輪詢?cè)L問(wèn)獲取數(shù)據(jù)
setInterval(() => {
render();
}, 500);
這樣我們是服務(wù)器資源很浪費(fèi)會(huì)一直的進(jìn)行訪問(wèn)api進(jìn)行獲取數(shù)據(jù)
我們說(shuō)了 客戶端不斷的向服務(wù)端進(jìn)行詢問(wèn)那么有沒(méi)有 服務(wù)端主動(dòng)向 客戶端進(jìn)行發(fā)送消息的呢 ?
SSE (server send event) 服務(wù)器推送數(shù)據(jù)
其是基于http協(xié)議的,本質(zhì)上是保持一個(gè)http長(zhǎng)連接,客戶端向服務(wù)端發(fā)送請(qǐng)求,在瀏覽器與服務(wù)器建立連接之后,等有數(shù)據(jù)更新后,服務(wù)端向?yàn)g覽器主動(dòng)發(fā)送消息。這樣可以減少數(shù)量,減少服務(wù)器壓力。
而在我們服務(wù)端使用sse的時(shí)候要進(jìn)行一些設(shè)置
設(shè)置頭部
"Content-type","text/event-stream"
返還數(shù)據(jù)格式
? data: 聲明數(shù)據(jù)開(kāi)始
? \r\n\r\n 標(biāo)志數(shù)據(jù)結(jié)尾
服務(wù)器端Node
我們?cè)O(shè)置兩個(gè)路由一個(gè)是返回首頁(yè) 第二個(gè)路由是進(jìn)行一些數(shù)據(jù)的返回也就是使用sse
const http = require("http");
const fs = require("fs");
// res.write(); res.end();
let server = http.createServer((req,res)=>{
let url = req.url;
//路由返回頁(yè)面
if(url=="/"){
let data = fs.readFileSync("index.html");
res.end(data);
}else if(url=="/sse"){
res.setHeader("content-type","text/event-stream;charset=utf-8");
// 服務(wù)端端定時(shí)推送數(shù)據(jù)到客戶端;
setInterval(() => {
res.write("data:時(shí)間是"+new Date()+"\r\n\r\n");
}, 1000);
}
})
server.listen(4000);
客戶端
我們需要?jiǎng)?chuàng)建一個(gè) EventSource對(duì)象 然后在這個(gè)對(duì)象里面有幾個(gè)事件
open:當(dāng)成功建立連接時(shí)產(chǎn)生
message:當(dāng)接收到消息時(shí)產(chǎn)生
error:當(dāng)出現(xiàn)錯(cuò)誤時(shí)產(chǎn)生
let source = new EventSource("/sse");
source.onopen = function(){
console.log("連接成功....");
console.log(source.readyState);
//這里的 readyState 會(huì)有幾種狀態(tài)
//- 0 CONNECTING (0)
//- 1 OPEN (1)
//- 2 CLOSED (2)
}
source.onmessage = function(e){
console.log("獲取到的數(shù)據(jù)是:",e.data);
document.querySelector(".exchange").innerHTML = e.data;
}
source.onerror = function(err){
return console.log(err);
}
這里的 readyState 會(huì)有幾種狀態(tài)
CONNECTING (0)
OPEN (1)
CLOSED (2)
以上的兩種方法雖然都能實(shí)現(xiàn)但是對(duì)性能都不是比較的友好 有沒(méi)有更好的解決方案呢?
websocket
WebSocket 是 HTML5 開(kāi)始提供的一種在單個(gè) TCP 連接上進(jìn)行全雙工通訊的協(xié)議
瀏覽器和服務(wù)器只需要完成一次握手,兩者之間就直接可以創(chuàng)建持久性的連接,并進(jìn)行雙向數(shù)據(jù)傳輸。
我們后端使用的是 Node 所以我們需要借助 ws 模塊創(chuàng)建 websocket 實(shí)例
ws是一種易于使用,快速且經(jīng)過(guò)全面測(cè)試的WebSocket客戶端和服務(wù)器實(shí)現(xiàn)的方法。
安裝npm install ws
簡(jiǎn)單使用
首先我們需要導(dǎo)入ws并調(diào)用Server 服務(wù)端
我們進(jìn)行設(shè)置端口
服務(wù)端
var WebSocketServer = require('ws').Server,
wss = new WebSocketServer({ port: 8181 });
wss.on('connection', function (ws){
console.log('client connected');
ws.on('message', function (message){
//監(jiān)聽(tīng)接收的數(shù)據(jù)
console.log(message);
});
// setInterval(() => {
let somedata = {
name:"張三",
age:20
}
//發(fā)送數(shù)據(jù)
ws.send(JSON.stringify(somedata));
// }, 1000);
});
客戶端
建立握手
var ws = new WebSocket("ws://localhost:8181");
打開(kāi)協(xié)議
ws.onopen = function (){}
發(fā)送數(shù)據(jù)到服務(wù)端
ws.send("客戶端數(shù)據(jù)");
關(guān)閉協(xié)議:關(guān)閉協(xié)議后不能發(fā)送數(shù)據(jù)
ws.close();
接收消息
ws.onmessage = function(e){
// console.log(e.data);
}
完整點(diǎn)的代碼
// 握手協(xié)議;
var ws = new WebSocket("ws://localhost:8181");
ws.onopen = function(){
console.log("連接成功....");
}
ws.onmessage = function(e){
// console.log(e.data);
console.log(JSON.parse(e.data));
}
function sub(){
ws.send("發(fā)送到服務(wù)端的數(shù)據(jù)");
}
整體就是簡(jiǎn)單的了解客戶端與服務(wù)端之間的交互問(wèn)題后面會(huì)更加詳細(xì)的進(jìn)行學(xué)習(xí)
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的ajax轮询模拟websocket,Ajax轮询和SSE服务器推送数据与websocket模式的区别性学习的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 封装svg组件
- 下一篇: RabbitMQ 延迟队列,消息延迟推送