前言
當(dāng)今web應(yīng)用程序?qū)?shí)時(shí)通信的需求越來(lái)越高,為了滿(mǎn)足客戶(hù)需求,輪詢(xún)和長(zhǎng)輪詢(xún)成為常用的技術(shù)手段。本文將深入講解一下輪詢(xún)實(shí)現(xiàn)原理、優(yōu)缺點(diǎn)和使用場(chǎng)景。
一、輪詢(xún)概念
輪詢(xún)是一種客戶(hù)端與服務(wù)器之間實(shí)時(shí)通信的技術(shù)手段。
基本原理:客戶(hù)端定期發(fā)送請(qǐng)求來(lái)查詢(xún)服務(wù)器是否有新數(shù)據(jù)或事件,并將響應(yīng)返回給客戶(hù)端。如果服務(wù)器有新的數(shù)據(jù)或事件,則將其返回給客戶(hù)端;如果沒(méi)有,則返回一個(gè)空響應(yīng)??蛻?hù)端收到響應(yīng)后,可以處理數(shù)據(jù)或事件,并根據(jù)需要繼續(xù)發(fā)送下一個(gè)請(qǐng)求。
定義:輪詢(xún)是指在一定的時(shí)間間隔內(nèi),定時(shí)向服務(wù)器發(fā)送請(qǐng)求,獲取最新數(shù)據(jù)的過(guò)程。輪詢(xún)通常用于從服務(wù)器獲取實(shí)時(shí)更新的數(shù)據(jù)。
// 客戶(hù)端代碼
function pollServer() {
fetch('/api/data')
.then(response => response.json())
.then(data => {
// 處理服務(wù)器響應(yīng)的數(shù)據(jù)
console.log('Received data:', data // 繼續(xù)下一次輪詢(xún)
setTimeout(pollServer, 5000);
});
}
// 開(kāi)始輪詢(xún)
pollServer();
二、輪詢(xún)的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):簡(jiǎn)單易實(shí)現(xiàn),適用于各種瀏覽器和服務(wù)器。
缺點(diǎn):輪詢(xún)會(huì)產(chǎn)生大量的無(wú)效請(qǐng)求,浪費(fèi)帶寬和服務(wù)器資源,產(chǎn)生不必要的網(wǎng)絡(luò)流量和延遲,并對(duì)服務(wù)器和客戶(hù)端資源造成額外的負(fù)擔(dān)。同時(shí),在短時(shí)間內(nèi)頻繁地發(fā)送請(qǐng)求可能會(huì)被服務(wù)器視為惡意行為,導(dǎo)致 IP 被封禁等問(wèn)題
注:輪詢(xún)適用于不需要實(shí)時(shí)性的應(yīng)用場(chǎng)景
三、長(zhǎng)輪詢(xún)概念
長(zhǎng)輪詢(xún)是一種改進(jìn)的輪詢(xún)技術(shù),其主要目的是降低輪詢(xún)過(guò)程中的資源消耗和延遲。長(zhǎng)輪詢(xún)的基本原理是客戶(hù)端發(fā)送一個(gè)HTTP請(qǐng)求給服務(wù)器,并保持連接打開(kāi),直到服務(wù)器有新的數(shù)據(jù)或事件時(shí)才返回響應(yīng)給客戶(hù)端。在這期間,服務(wù)器會(huì)一直保持連接打開(kāi),直到超時(shí)或有新數(shù)據(jù)或事件
// 客戶(hù)端代碼
function longPollServer() {
fetch('/api/data')
.then(response => {
if (response.status === 204) {
// 服務(wù)器返回204表示沒(méi)有新數(shù)據(jù)或事件,繼續(xù)進(jìn)行長(zhǎng)輪詢(xún)
longPollServer();
} else if (response.status === 200) {
// 服務(wù)器返回200表示有新數(shù)據(jù)或事件,處理數(shù)據(jù)并進(jìn)行下一次長(zhǎng)輪詢(xún)
response.json().then(data => {
console.log('Received data:', data);
// 繼續(xù)進(jìn)行長(zhǎng)輪詢(xún)
longPollServer();
});
}
});
}
//開(kāi)始長(zhǎng)輪詢(xún)
longPollServer
四、長(zhǎng)輪詢(xún)的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):長(zhǎng)輪詢(xún)相較于輪詢(xún)技術(shù)來(lái)說(shuō),減少了不必要的網(wǎng)絡(luò)流量和請(qǐng)求次數(shù),降低了服務(wù)器和客戶(hù)端的資源消耗
缺點(diǎn):相對(duì)于傳統(tǒng)的輪詢(xún)技術(shù),長(zhǎng)輪詢(xún)的實(shí)現(xiàn)更加復(fù)雜,并且需要服務(wù)器支持長(zhǎng)時(shí)間保持連接的能力。
注:長(zhǎng)輪詢(xún)適用于對(duì)實(shí)時(shí)性要求較高的應(yīng)用場(chǎng)景,例如在線游戲、即時(shí)消息推送等。在這些場(chǎng)景下,降低延遲和減少不必要的資源消耗對(duì)于提供良好的用戶(hù)體驗(yàn)非常重要。
五、輪詢(xún)和長(zhǎng)輪詢(xún)的區(qū)別比較
輪詢(xún)和長(zhǎng)輪詢(xún)都是實(shí)現(xiàn)客戶(hù)端與服務(wù)器實(shí)時(shí)通信的技術(shù)手段,它們?cè)谫Y源消耗、延遲和實(shí)時(shí)性等方面存在差異。
輪詢(xún)是在固定的時(shí)間間隔內(nèi)向服務(wù)器發(fā)送請(qǐng)求,即使服務(wù)器沒(méi)有數(shù)據(jù)更新也會(huì)繼續(xù)發(fā)送請(qǐng)求(不需要實(shí)時(shí)性要求很高的場(chǎng)景)。
長(zhǎng)輪詢(xún)是先發(fā)送一個(gè)請(qǐng)求,服務(wù)器如果沒(méi)有數(shù)據(jù)更新,則不會(huì)立即返回,而是將請(qǐng)求掛起,直到有數(shù)據(jù)更新時(shí)再返回結(jié)果(對(duì)實(shí)時(shí)性要求較高的場(chǎng)景)。
六、示例代碼
案例1:使用輪詢(xún)實(shí)現(xiàn)實(shí)時(shí)時(shí)間更新的簡(jiǎn)單示例代碼:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-806168.html
// 客戶(hù)端代碼
function pollServer() {
發(fā)送HTTP請(qǐng)求給服務(wù)器
fetch('/api/time')
.then(response => response.json())
.then(data => {
// 處理服務(wù)器響應(yīng)的時(shí)間數(shù)據(jù)
const currentTime = new Date(data.time);
document.getElementById('time').innerText = currentTime.toLocaleTimeString();
// 繼續(xù)下一次輪詢(xún)
setTimeout(pollServer, 5000);
});
}
// 開(kāi)始輪詢(xún)
pollServer();
案例2:可視化動(dòng)態(tài)展示數(shù)據(jù),有的需要十秒輪詢(xún)請(qǐng)求一次,有的需要3分鐘請(qǐng)求一次,有的需要一天一次(順便加一個(gè)定時(shí),每天幾點(diǎn)鐘定時(shí)請(qǐng)求一次)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-806168.html
<template>
<div class="echart">
</div>
</template>
<script>
export default {
data() {
return {
num_0:0,
num_1:0,
num_2:0,
timer_10: null,//10S短輪詢(xún)
timer_3: null, //3分鐘短輪詢(xún)
timer_24: null, //24小時(shí)長(zhǎng)輪詢(xún)
};
},
destroyed() {
//離開(kāi)頁(yè)面是時(shí)記得銷(xiāo)毀
this.clearAll()
},
created() {
// 進(jìn)入頁(yè)面開(kāi)始請(qǐng)求
this.getShotList3()
this.getShotList10()
this.getLongList()
// 開(kāi)啟定時(shí)
this.startRequest()
},
methods: {
startRequest() {
//10S短輪詢(xún):組合使用setInterval setTimeout實(shí)現(xiàn)輪詢(xún)可解決瀏覽器崩潰
this.timer_10 = window.setInterval(() => {
setTimeout(this.getShotList10(), 0);
},10000);
// 3分鐘短輪詢(xún)
this.timer_3 = window.setInterval(() => {
setTimeout(this.getShotList3(), 0);
}, 180000);
// 每日一次的輪詢(xún):每日定點(diǎn)7點(diǎn)查詢(xún)一次;計(jì)算當(dāng)前時(shí)間和目標(biāo)時(shí)間的時(shí)間間隔,如果超過(guò),則設(shè)置定時(shí)查詢(xún)的時(shí)間間隔為距離明天目標(biāo)小時(shí)的距離,如果還沒(méi)到就設(shè)置時(shí)間為當(dāng)前時(shí)間到目標(biāo)小時(shí)的距離。
this.setRegular(7);
},
setRegular(targetHour) {
let nowTime = new Date()
let nowSeconds = nowTime.getHours() * 3600 + nowTime.getMinutes() * 60 + nowTime.getSeconds() // 計(jì)算當(dāng)前時(shí)間的秒數(shù)
let targetSeconds = targetHour * 3600 // 計(jì)算目標(biāo)時(shí)間對(duì)應(yīng)的秒數(shù)
// 判斷是否已超過(guò)今日目標(biāo)鐘點(diǎn)數(shù),若超過(guò),時(shí)間間隔設(shè)置為距離明天目標(biāo)小時(shí)的距離
let timeInterval = targetSeconds > nowSeconds ? targetSeconds - nowSeconds: targetSeconds + 24 * 3600 - nowSeconds
this.timer_24 = window.setInterval(() => {
setTimeout(this.getLongList(), 0)
}, timeInterval * 1000);
},
getLongList() {
console.log("24小時(shí)輪詢(xún)" + this.num_0++ + "次");
},
clearAll() {
clearInterval(this.timer_10);
clearInterval(this.timer_3);
clearInterval(this.timer_24);
this.timer_10 = null;
this.timer_3 = null;
this.timer_24 = null;
console.log('銷(xiāo)毀');
},
// 10S的短輪詢(xún) 數(shù)據(jù)全部拿到之后在進(jìn)行下一次請(qǐng)求
getShotList10() {
console.log("10秒鐘請(qǐng)求" + this.num_1++ + "次");
},
// 3分鐘的短輪詢(xún) 數(shù)據(jù)全部拿到之后在進(jìn)行下一次請(qǐng)求
getShotList3() {
console.log("3分鐘請(qǐng)求" + this.num_2++ + "次");
},
}
}
</script>
<style scoped>
.echart{
width:100%;
height:100%
}
</style>
到了這里,關(guān)于輪詢(xún)和長(zhǎng)輪詢(xún)的講解和實(shí)戰(zhàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!