例如,我想使用socket.io、长轮询等技术来在多个选项卡中刷新聊天消息。为此,我希望只使用一个连接处理所有选项卡。我该如何实现?可以将公共数据存储在localStorage、cookie等中,并且需要某种信号量,使得一个选项卡只能获取一个同步资源,在该选项卡关闭后,它将分配给另一个选项卡,以此类推。这是否可行?唯一想到的解决方法是告诉localStorage在onbeforeunload时释放资源,但这在每个浏览器中都不起作用。是否有其他选项?
localStorage
支持 vs postMessage
支持。除了Opera Mini之外,localStorage
在所有设备上都得到支持,而同源的postMessage
在IE 8-9之外的所有设备上都得到支持,因此取决于您的目标受众,哪个更可取。 - Tgr我已经为浏览器标签实现了相同的方法。共享工作线程首先选择浏览器标签中的“主要”标签。一个问候消息会持续广播到所有浏览器标签,并且每个标签都会回复它们是主要还是备份。如果主要标签没有回应,那么共享工作线程会选择一个备份标签,并指示它成为主要标签。
代码的关键部分是心跳函数,它每5秒钟(默认值)执行以下操作:(1)移除无响应的页面;(2)如有必要选择新的主要标签;(3)对所有浏览器标签进行ping操作。
this.heartbeat = function() {
self.purgeDeadPages();
self.selectPrime();
self.ping();
}
selectPrime函数计算报告自身为素数的页面数量:如果为0,则必须选择一个新的素数;如果>1,则是一种退化条件,除了一个素数之外,其它都必须“备份”。
this.selectPrime = function() {
let primes = this.getPrimes();
if(primes.length == 0) {
let backups = this.getBackups();
if(backups.length > 0) {
let newPrime = backups.length == 1 ? backups[0] : backups[Math.floor(Math.random() * backups.length)];
this.goPrime(newPrime);
self.pages[newPrime].setStatus(iAmPrimeMessage);
}
} else if(primes.length > 1) {
let newPrime = primes[Math.floor(Math.random() * primes.length)];
primes.forEach((prime) => {
if(prime != newPrime) {
this.goBackup(prime);
self.pages[prime].setStatus(iAmBackupMessage);
}
});
}
}
所有的代码和测试框架都在https://github.com/RundleAutomation/Failover上。