文章目录
- 一、BroadCast Channel
- 二、Service Worker
- 三、LocalStorage window.onstorage监听
- 四、Shared Worker(定时器轮询)
- 五、IndexedDB定时器轮询
- 六、cookie定时器轮询
- 七、window.open、window.postMessage
- 八、WebSocket
一、BroadCast Channel
页面一:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>页面一</title>
</head>
<body>
<input type="text" name="" id="content">
<button id="btn">发送数据</button>
<script>
const content = document.querySelector("#content")
const btn = document.querySelector("#btn")
//创建一个广播频道
const broadCastChannel=new BroadcastChannel("load") //对象
btn.onclick=function (){
broadCastChannel.postMessage({
value:content.value
})
}
</script>
</body>
</html>
页面二:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>页面二</title>
</head>
<body>
<script>
//传入的字符串要和页面一的一样
const broadCastChannel=new BroadcastChannel("load") //对象
//监听消息
broadCastChannel.onmessage=function (e) {
console.log(e.data.value)
}
</script>
</body>
</html>
二、Service Worker
service worker实际上是浏览器和服务器之间的代理服务器,它最大的特点是在页面中注册并安装成功后,运行于浏览器后台,不受页面刷新的影响,可以监听和截拦作用域范围内所有页面的http请求。
service worker的目的在于离线缓存,转发请求和网络代理。
页面一:
const content = document.querySelector("#content")
const btn = document.querySelector("#btn")
//注册service worker
navigator.serviceWorker.register('sw.js').then(()=>{
console.log("注册成功")
})
btn.onclick=function () {
navigator.serviceWorker.controller.postMessage({
value:content.value
})
}
页面二:
//注册service worker
navigator.serviceWorker.register('sw.js').then(()=>{
console.log("注册成功")
})
navigator.serviceWorker.onmessage=function ({data}){
console.log(data)
}
sw.js:
//消息就会到达这里
self.addEventListener('message', async event => {
//获取所有注册了service worker的客户端
const clients=await self.clients.matchAll();
clients.forEach(client => {
client.postMessage(event.data)
})
})
三、LocalStorage window.onstorage监听
页面一:
localStorage.age="20"
localStorage.name="崔"
localStorage.sex="女"
页面二:
window.onstorage=function (e){
console.log("测试",e)
}
四、Shared Worker(定时器轮询)
Shared Worker接口代表一种特定类型的worker,可以从几个浏览上下文中访问,例如几个窗口、iframe或其他worker。它们实现一个不同于普通worker的接口,具有不同的全局作用域,如果要使Shared Worker连接到多个不同的页面,这些页面必须是同源的
页面一:
//创建一个worker
const worker=new SharedWorker('./worker.js')
btn.onclick=function(){
console.log(worker)
worker.port.postMessage(content.value)
}
页面二:
const worker=new SharedWorker("worker.js")
worker.port.start()
worker.port.onmessage=function (e){
if(e.data){
console.log("收到的数据",e)
}
}
//轮询
setInterval(()=>{
worker.port.postMessage("get")
},1000)
worker.js:
let data = "" //存储用户发送过来的信息
self.addEventListener("connect", function (e) {
console.log("进来了")
let port = e.ports[0];
port.onmessage = function (e) {
//将接收到的数据返回给客户端
if (e.data === 'get') {
port.postMessage(data)
} else {
data = e.data
}
}
})
五、IndexedDB定时器轮询
页面一:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>页面一</title>
</head>
<body>
<h1>新增学生</h1>
<div>
<span>学生ID:</span>
<input type="text" name="stuId" id="stuId">
</div>
<div>
<span>学生姓名:</span>
<input type="text" name="stuName" id="stuName">
</div>
<div>
<span>学生年龄名:</span>
<input type="text" name="stuAge" id="stuAge">
</div>
<button id="addBtn">新增学生</button>
<script src="db.js"></script>
<script>
let btn = document.querySelector("#addBtn")
let stuId = document.querySelector("#stuId")
let stuName = document.querySelector("#stuName")
let stuAge = document.querySelector("#stuAge")
openDB("stuDB", 1).then((db) => {
btn.onclick = function () {
// deleteDataById(db,"stu",0)
addData(db, "stu", {
"stuId": Number(stuId.value),
"stuName": stuName.value,
"stuAge": stuAge.value
})
stuId.value = stuName.value = stuAge.value = ""
}
})
</script>
</body>
</html>
页面二:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>页面二</title>
<style>
table {
border: 1px solid;
border-collapse: collapse;
}
table td {
border: 1px solid;
}
</style>
</head>
<body>
<table id="tab">
</table>
<script src="db.js"></script>
<script>
function render(arr) {
let tab = document.querySelector("#tab")
tab.innerHTML = `
<tr>
<td>学号</td>
<td>姓名</td>
<td>年龄</td>
</tr>
`
let str = arr.map(item => {
return `
<tr>
<td>${item.stuId}</td>
<td>${item.stuName}</td>
<td>${item.stuAge}</td>
</tr>
`
}).join("")
tab.innerHTML += str
}
async function renderTable() {
let db = await openDB("stuDB", 1)
let stuInfo = await getAllData(db, "stu")
render(stuInfo)
setInterval(async () => {
let stuInfo2 = await getAllData(db, "stu")
if (stuInfo2.length !== stuInfo.length) {
stuInfo = stuInfo2
render(stuInfo)
}
}, 1000)
}
renderTable()
</script>
</body>
</html>
db.js:
/**
*
* @param dbName 数据库名称
* @param version 数据库版本
*/
function openDB(dbName, version = 1) {
return new Promise((resolve, reject) => {
let db;//存储数据库对象
//打开数据库,没有则创建操作
let request = indexedDB.open(dbName, version)
//数据库打开或者创建成功的时候
request.onsuccess = function (event) {
db = event.target.result;
console.log("打开成功")
resolve(db)
}
request.onerror = function (res) {
console.log("打开失败")
}
//版本号更新 添加或者删除对象仓库(表)的时候
//第一次调用open方法的时候会触发这个事件
//初始化表
request.onupgradeneeded = function (event) {
console.log("更新")
db = event.target.result;
let objectStore = db.createObjectStore("stu", {
keyPath: "stuId", //主键
autoIncrement: true,//自增
})
//创建索引 增大查询速度
objectStore.createIndex("stuId", "stuId", {unique: true})
objectStore.createIndex("stuName", "stuName", {unique: false})
objectStore.createIndex("stuAge", "stuAge", {unique: false})
}
})
}
/**
* 关闭数据库
* @param dbName 数据库名称
*/
function closeDB(dbName) {
dbName.close()
}
/**
*删除数据库
* @param dbName 数据库名称
*/
function deleteDB(dbName) {
// deleteRequest 操作请求对象
let deleteRequest = window.indexedDB.deleteDatabase(dbName);
deleteRequest.onsuccess = function (event) {
console.log("删除成功")
}
deleteRequest.onerror = function (res) {
console.log("删除失败")
}
}
/**
*添加数据
* @param db 数据库实例
* @param storeName 数据库仓库实例(表)
* @param data 要添加的数据
*/
function addData(db, storeName, data) {
//transaction 事务
let request = db.transaction([storeName], "readwrite").objectStore(storeName).add(data)
request.onsuccess = function (event) {
console.log("写入成功")
}
request.onerror = function (res) {
console.log("写入失败")
}
}
/**
* 通过主键读取数据
* @param db 数据库实例
* @param storeName 仓库名称
* @param key 主键
* @returns {Promise<unknown>}
*/
function getDataByKey(db, storeName, key) {
return new Promise((resolve, reject) => {
let transaction = db.transaction([storeName]) //事务
let objectStore = transaction.objectStore(storeName) //仓库对象
let request = objectStore.get(key) //通过主键获取数据
request.onsuccess = function (event) {
console.log("主键查询结果:", request.result)
resolve(request.result)
}
request.onerror = function (res) {
console.log("事务失败")
}
})
}
/**
* 获取全部数据
* @param db 数据库实例
* @param storeName 仓库名称
* @returns {Promise<unknown>}
*/
function getAllData(db, storeName) {
return new Promise((resolve, reject) => {
let transaction = db.transaction([storeName]) //事务
let objectStore = transaction.objectStore(storeName) //仓库对象
let request = objectStore.getAll() //通过主键获取数据
request.onsuccess = function (event) {
resolve(request.result)
}
request.onerror = function (res) {
console.log("事务失败")
}
})
}
/**
*通过主键删除数据 (delete方法)
* @param db
* @param storeName
* @param data 数据
*/
function deleteDataById(db, storeName, id) {
return new Promise((resolve, reject) => {
let request = db.transaction([storeName], "readwrite").objectStore(storeName).delete(id)
request.onsuccess = function (event) {
resolve({
status: "success",
message: "删除数据成功"
})
}
request.onerror = function (res) {
reject({
status: "error",
message: "删除数据失败"
})
}
})
}
六、cookie定时器轮询
页面一:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>页面一</title>
</head>
<body>
<input type="text" name="" id="content">
<button id="btn">发送数据</button>
<script>
document.cookie="name=小吴"
console.log("设置成功")
</script>
</body>
</html>
页面二:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>页面二</title>
</head>
<body>
<script>
let cookie=document.cookie
console.log(`当前得cookie值为:${cookie}`)
setInterval(()=>{
if(document.cookie!==cookie){
cookie=document.cookie
console.log(`最新得值为${document.cookie}`)
}
},1000)
</script>
</body>
</html>
七、window.open、window.postMessage
页面一:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>页面一</title>
</head>
<body>
<button id="popBtn">弹出新窗口</button>
<input type="text" name="" id="content">
<button id="btn">发送数据</button>
<script>
const content = document.querySelector("#content")
const btn = document.querySelector("#btn")
const popBtn = document.querySelector("#popBtn")
let opener=null //用于保存window.open打开得窗口引用
popBtn.onclick=function () {
opener=window.open("index2.html","12131","height=400,width=400,top=20,resizeable=yes")
}
btn.onclick=function(){
let data={value:content.value}
//data代表得是要发送得数据,第二个参数是origin,使用*代表所有域
opener.postMessage(data,"*")
}
</script>
</body>
</html>
页面二:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>页面二</title>
</head>
<body>
<p>
这是页面二
</p>
<script>
window.addEventListener('message',function (e) {
console.log(e.data)
})
</script>
</body>
</html>
八、WebSocket
最大特点就是,服务器可以主动向客户端推送信息,而非客户端采用轮询得方法,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
页面一:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>页面一</title>
</head>
<body>
<input type="text" name="" id="msg">
<button id="send">发送信息</button>
<script>
//建立websocket连接
let ws=new WebSocket("ws://localhost:3000")
let send=document.querySelector("#send")
let msg=document.querySelector("#msg")
send.onclick=function () {
if(msg.value.trim()!==''){
ws.send(msg.value.trim())
let op1=document.createElement("p")
op1.innerHTML=`我:${msg.value}`
if(msg.value.trim()!==''){
document.body.appendChild(op1)
}
msg.value=''
}
}
let count=1 //用于计数
ws.onopen=function () {
ws.onmessage=function (event) {
let op=document.createElement("p")
op.innerHTML=`你:${event.data}`
document.body.appendChild(op)
count++
}
}
//关闭窗口或者刷新得时候关闭webSocket连接
window.onbeforeunload=function () {
ws.close()
}
</script>
</body>
</html>
页面二:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>页面二</title>
</head>
<body>
<input type="text" name="" id="msg">
<button id="send">发送信息</button>
<script>
//建立websocket连接
let ws=new WebSocket("ws://localhost:3000")
let send=document.querySelector("#send")
let msg=document.querySelector("#msg")
send.onclick=function () {
if(msg.value.trim()!==''){
ws.send(msg.value.trim())
let op1=document.createElement("p")
op1.innerHTML=`我:${msg.value}`
if(msg.value.trim()!==''){
document.body.appendChild(op1)
}
msg.value=''
}
}
let count=1 //用于计数
ws.onopen=function () {
ws.onmessage=function (event) {
let op=document.createElement("p")
op.innerHTML=`你:${event.data}`
document.body.appendChild(op)
count++
}
}
//关闭窗口或者刷新得时候关闭webSocket连接
window.onbeforeunload=function () {
ws.close()
}
</script>
</body>
</html>
websocket.js:
//获取WebSocketServer实例
let WebSocketServer = require("ws").Server
//创建websocket服务器
let wss = new WebSocketServer({
port: 3000
});
//该数组用于保存所有得客户端连接实例
let clients =[]
//客户端连接上websocket服务器得时候就会触发connection事件,该客户端得实例就会传入此回调函数
wss.on('connection', function (client) {
//保存客户端实例到clients
clients.push(client);
console.log("当前在线客户端数量:",clients.length)
//给传入进来得客户端连接实例绑定一个message事件
client.on('message', function (message) {
console.log("收到得消息"+message)
//图将接收到得信息推送给其他所有客户端
for(let item of clients) {
//排除自己,client:当前客户端
if(item!==client){
item.send(message.toString())
}
}
})
client.on('close', function () {
let index=clients.indexOf(this)
clients.splice(index,1)
console.log("当前在线客户端数量:",clients.length)
})
})
console.log("websocket服务器启动")
效果如图: