当前位置:网站首页>Cross page communication
Cross page communication
2022-07-05 10:47:00 【Code Bruce Lee】
Cross page communication
Preface
You often encounter the need to share information across tags , Then this article will review with you web What are the ways to realize such requirements .
Solution
websocket
var ws = new WebSocket(“wss://echo.websocket.org”);
ws.onopen = function(evt) {
console.log(“Connection open …”);
ws.send(“Hello WebSockets!”);
};
ws.onmessage = function(evt) {
console.log( "Received Message: " + evt.data);
ws.close();
};
ws.onclose = function(evt) {
console.log(“Connection closed.”);
};
Reference material :websocket course ( Ruan Yifeng )
localStorage Listening in
localstorge Add... In a tab 、 When modified or deleted , Will trigger a storage event , By listening on another tab storage event , You can get localstorge Stored values , Realize the communication between different tabs .
$(function(){
window.addEventListener(“storage”, function(event){
console.log(event.key );
console.log(event.oldValue);
console.log(event.newValue);
console.log(event.url); // What is currently changing url
});
});
The timer monitors cookie
Use cookie+setInterval, Store the information to be delivered in cookie in , Read at regular intervals cookie Information , You can get the information you want to transfer at any time .
$(function(){
setInterval(function(){
var value=cookieUtil.get(‘name’);
console.log(value);
}, 10000);
});
BroadCast Channel – postMessage
It is suitable for cross page communication with the same source , Can help us create a communication channel for broadcasting . When all pages listen for messages on the same channel , The message sent by one page will be received by all other pages . its API And usage are very simple .
In the following way, you can create an ID as AlienZHOU Channel :
const bc = new BroadcastChannel(‘AlienZHOU’);
Each page can be accessed through onmessage To listen to the broadcast message :
bc.onmessage = function (e) {
const data = e.data;
const text = ‘[receive] ’ + data.msg + ’ —— tab ’ + data.from;
console.log(’[BroadcastChannel] receive message:‘, text);
};
// To send a message, you only need to call postMessage The method can :
bc.postMessage(mydata);
service worker
Service Worker It is a system that can run in the background for a long time Worker, It can realize two-way communication with the page . Multi page sharing Service Worker Can be Shared , take Service Worker As the processing center of messages ( Central station ) The broadcast effect can be realized .
First , You need to register on the page Service Worker:
/ Page logic /
navigator.serviceWorker.register(’…/util.sw.js’).then(function () {
console.log(‘Service Worker Registered successfully ’);
});
among …/util.sw.js Is the corresponding Service Worker Script .Service Worker It does not automatically have “ Broadcast communications ” The function of , We need to add some code , Transform it into a message transfer station :
/* …/util.sw.js Service Worker Logic /
self.addEventListener(‘message’, function (e) {
console.log(‘service worker receive message’, e.data);
e.waitUntil(
self.clients.matchAll().then(function (clients) {
if (!clients || clients.length === 0) {
return;
}
clients.forEach(function (client) {
client.postMessage(e.data);
});
})
);
});
We are Service Worker I'm listening in message event , Access to the page ( from Service Worker The angle is client) Messages sent . And then through self.clients.matchAll() Get the currently registered Service Worker All pages of , By calling each client( Page ) Of postMessage Method , Send a message to the page . This will take you from one place ( Some Tab page ) The message received is notified to other pages .
processed Service Worker, We need to listen on the page Service Worker Messages sent :
/ Page logic /
navigator.serviceWorker.addEventListener(‘message’, function (e) {
const data = e.data;
const text = ‘[receive] ’ + data.msg + ’ —— tab ’ + data.from;
console.log(’[Service Worker] receive message:', text);
});
// Last , When you need to synchronize messages , You can call Service Worker Of postMessage Method :
/ Page logic */
navigator.serviceWorker.controller.postMessage(mydata);
indexDB
The message sender saves the message to IndexedDB in ; The receiving party ( For example, all pages ) Then get the latest information by polling . before this , Let's simply package a few IndexedDB The tool method of .
Open database connection :
function openStore() {
const storeName = ‘ctc_aleinzhou’;
return new Promise(function (resolve, reject) {
if (!(‘indexedDB’ in window)) {
return reject(‘don’t support indexedDB’);
}
const request = indexedDB.open(‘CTC_DB’, 1);
request.onerror = reject;
request.onsuccess = e => resolve(e.target.result);
request.onupgradeneeded = function (e) {
const db = e.srcElement.result;
if (e.oldVersion === 0 && !db.objectStoreNames.contains(storeName)) {
const store = db.createObjectStore(storeName, {keyPath: ‘tag’});
store.createIndex(storeName + ‘Index’, ‘tag’, {unique: false});
}
}
});
}
// Store the data
function saveData(db, data) {
return new Promise(function (resolve, reject) {
const STORE_NAME = ‘ctc_aleinzhou’;
const tx = db.transaction(STORE_NAME, ‘readwrite’);
const store = tx.objectStore(STORE_NAME);
const request = store.put({tag: ‘ctc_data’, data});
request.onsuccess = () => resolve(db);
request.onerror = reject;
});
}
// Inquire about / Reading data
function query(db) {
const STORE_NAME = ‘ctc_aleinzhou’;
return new Promise(function (resolve, reject) {
try {
const tx = db.transaction(STORE_NAME, ‘readonly’);
const store = tx.objectStore(STORE_NAME);
const dbRequest = store.get(‘ctc_data’);
dbRequest.onsuccess = e => resolve(e.target.result);
dbRequest.onerror = reject;
}
catch (err) {
reject(err);
}
});
}
The rest of the work is very simple . First open the data connection , And initialize the data :
openStore().then(db => saveData(db, null))
// For message reading , You can poll after connection and initialization :
openStore().then(db => saveData(db, null)).then(function (db) {
setInterval(function () {
query(db).then(function (res) {
if (!res || !res.data) {
return;
}
const data = res.data;
const text = ‘[receive] ’ + data.msg + ’ —— tab ’ + data.from;
console.log(’[Storage I] receive message:', text);
});
}, 1000);
});
// Last , When you want to send a message , Just to IndexedDB Just store the data :
openStore().then(db => saveData(db, null)).then(function (db) {
// …… Omit the polling code above
// Trigger saveData The method of can be put in the event listening of user operation
saveData(db, mydata);
});
window.open + window.opener( Homologous page )
When we use window.open When opening a page , Method will return an open page window References to . While the specified noopener when , The opened page can be accessed through window.opener Get the reference to the page that opened it —— In this way, we have established a connection between these pages ( A tree structure ).
First , We put window.open Of the open page window Collect objects :
let childWins = [];
document.getElementById(‘btn’).addEventListener(‘click’, function () {
const win = window.open(‘./some/sample’);
childWins.push(win);
});
then , When we need to send messages , As the initiator of the message , A page needs to notify it of both the page it opens and the page it opens :
// Filter out closed windows
childWins = childWins.filter(w => !w.closed);
if (childWins.length > 0) {
mydata.fromOpenner = false;
childWins.forEach(w => w.postMessage(mydata));
}
if (window.opener && !window.opener.closed) {
mydata.fromOpenner = true;
window.opener.postMessage(mydata);
}
Be careful , I'll use it here first .closed Property to filter out the closed Tab window . such , The task of being the sender of the message is completed . Let's see below. , As a message receiver , What does it need to do .
here , A page that receives messages cannot be so selfish , In addition to displaying the received messages , It also needs to deliver the message to it “ People who know ”( Open and the page it opens ):
It should be noted that , I judge the source here , Avoid sending messages back to the sender , Prevent messages from being transmitted in an endless loop between the two .( There will be some other minor problems with this scheme , In practice, it can be further optimized )
window.addEventListener(‘message’, function (e) {
const data = e.data;
const text = ‘[receive] ’ + data.msg + ’ —— tab ’ + data.from;
console.log(’[Cross-document Messaging] receive message:', text);
// Avoid message return
if (window.opener && !window.opener.closed && data.fromOpenner) {
window.opener.postMessage(data);
}
// Filter out closed windows
childWins = childWins.filter(w => !w.closed);
// Avoid message return
if (childWins && !data.fromOpenner) {
childWins.forEach(w => w.postMessage(data));
}
});
such , Every node ( page ) Have shouldered the responsibility of delivering messages , That's what I said “ Word of mouth ”, And the message flows in this tree structure .
iframe Non homologous page
In my special article on cross domain solution, I introduce the code scheme in detail , The idea is as follows :
边栏推荐
- [vite] 1371 - develop vite plug-ins by hand
- Atcoder beginer contest 254 "e BFS" f st table maintenance differential array GCD "
- Crawler (9) - scrape framework (1) | scrape asynchronous web crawler framework
- Pull up loading principle
- dsPIC33EP 时钟初始化程序
- 5G NR系统架构
- 九度 1480:最大上升子序列和(动态规划思想求最值)
- 2022年危险化学品生产单位安全生产管理人员特种作业证考试题库模拟考试平台操作
- Learning note 4 -- Key Technologies of high-precision map (Part 2)
- Customize the left sliding button in the line in the applet, which is similar to the QQ and Wx message interface
猜你喜欢
【DNS】“Can‘t resolve host“ as non-root user, but works fine as root
How does redis implement multiple zones?
2022年流动式起重机司机考试题库及模拟考试
Based on shengteng AI Aibi intelligence, we launched a digital solution for bank outlets to achieve full digital coverage of information from headquarters to outlets
In the year of "mutual entanglement" of mobile phone manufacturers, the "machine sea tactics" failed, and the "slow pace" playing method rose
2022年T电梯修理操作证考试题及答案
重磅:国产IDE发布,由阿里研发,完全开源!
ModuleNotFoundError: No module named ‘scrapy‘ 终极解决方式
2022鹏城杯web
AD20 制作 Logo
随机推荐
Web3基金会「Grant计划」赋能开发者,盘点四大成功项目
字符串、、
vite//
微信核酸检测预约小程序系统毕业设计毕设(8)毕业设计论文模板
Blockbuster: the domestic IDE is released, developed by Alibaba, and is completely open source!
Broyage · fusion | savoir que le site officiel de chuangyu mobile end est en ligne et commencer le voyage de sécurité numérique!
Learning notes 5 - high precision map solution
2022年危险化学品生产单位安全生产管理人员特种作业证考试题库模拟考试平台操作
Idea create a new sprintboot project
关于vray 5.2的使用(自研笔记)(二)
2022年化工自动化控制仪表考试试题及在线模拟考试
【黑马早报】罗永浩回应调侃东方甄选;董卿丈夫密春雷被执行超7亿;吉利正式收购魅族;华为发布问界M7;豆瓣为周杰伦专辑提前开分道歉...
Who is the "conscience" domestic brand?
[paper reading] ckan: collaborative knowledge aware autonomous network for adviser systems
GO项目实战 — Gorm格式化时间字段
websocket
32: Chapter 3: development of pass service: 15: Browser storage media, introduction; (cookie,Session Storage,Local Storage)
Pull up loading principle
微信核酸检测预约小程序系统毕业设计毕设(6)开题答辩PPT
C语言活期储蓄账户管理系统