Browser multi-tab communication

  javascript

Browser multi-tab communication helps to reduce server load, improve operating efficiency and improve user experience. It is an important link in front-end development and optimization.

Source of demand

On the background of most CMS (content management system), it is common to have an article list page. Clicking on a list item will open a new article details page. Editors often manipulate articles on this detail page, such as modifying titles, diagrams, summaries, etc. After the operation is completed, since the article page and the list page are two pages, the article content data cannot be synchronized to the list in time, thus the operator is mistaken for many times, which greatly reduces the work efficiency of the operator.

For front-end engineers, it is an important thing to realize the communication between multiple page cards of the browser and update relevant data changes in time.
图片描述

For example, there is a requirement: when the article details page is updated, it will go to the article list page at the same time.

Implementation mode

Method 1: cookie+setInterval

Cookie are initially used at the client to store the user’s session information. Since HTTP is a stateless protocol, the server cannot know the identity of the client from the network connection alone. Through cookie, clients will be issued with a pass, one for each, and whoever visits must carry his own pass. In this way, the server can confirm the customer’s identity from the pass. Cookie is actually a small piece of text information. The client requests the server to issue a cookie to the client browser if the server needs to record the user’s status. The client browser will save the cookie. When the browser requests the website again, the browser submits the requested website address to the server together with the cookie. The server checks the cookie to identify the user’s status. The server can also modify the cookie content as needed.

In JavaScript, the cookie’s operation interface is document.cookie, through which cookies can be read, written and deleted. This operation is actually not very friendly, so many tool libraries provide cookie operation methods. I provide a simple packaging method here.

var QQ = {};
QQ.Cookie={
set:function(name,value,expires,path,domain){
if(typeof expires=="undefined"){
expires=new Date(new Date().getTime()+3600*1000);
}
document.cookie=name+"="+escape(value)+((expires)?  ";   expires="+expires.toGMTString():"")+((path)?  ";   path="+path:";   path=/")+((domain)?  ";  domain="+domain:"");
},
get:function(name){
var arr=document.cookie.match(new RegExp("(^| )"+name+"=([^;  ]*)(;  |$)"));
if(arr!  =null){
return unescape(arr[2]);
}
return null;
},
clear:function(name,path,domain){
if(this.get(name)){
document.cookie=name+"="+((path)?  ";   path="+path:";   path=/")+((domain)?  ";   domain="+domain:"")+";  expires=Fri, 02-Jan-1970 00:00:00 GMT";
}
}
};

Cookies have a feature that cookies generated by a page can be accessed by pages in the same directory or other subdirectories of the page, thus creating a shared storage space between pages. Usually, the cookie’s path is set to a higher level directory, such as the default “/”,so that more pages share cookies and multiple pages communicate with each other. The domain in which the cookie is located defaults to the requested address, and the domain that the cookie can be accessed can also be expanded by setting document.domain as the parent domain.

Implementation principle:

The list page cyclically monitors cookie data changes through the setInterval timer.
List page code:

window.onload=function(){
var tid =  '';
setInterval(function(){
if(tid !  = QQ.Cookie.get("tid")){
Alert ('Data Update!'  );
tid = QQ.Cookie.get("tid")
}
}, 1000);
}

When the details page has data modification, write cookie
Details page code:

<input id="content" type="text">
 <button id="btn">Click</button>
 <script>
 window.onload=function(){
 var oBtn=document.getElementById("btn");
 var oInput=document.getElementById("content");
 oBtn.onclick=function(){
 var val=oInput.value;
 QQ.Cookie.set("tid",val);
 }
 }
 </script>

Cookie+setIntervalinsufficient

1. cookie space is limited. The browser can set up a maximum of 30-50 cookies under each domain name, with a maximum capacity of about 4K.
2. Every HTTP request will send cookies of the current domain to the server, while some cookies are only used by browsers, wasting network bandwidth.
3. The frequency setting of setInterval will affect browser performance if it is too large, and timeliness if it is too small.

Advantages of cookie+setInterval:

Compatibility is good, almost all browsers support it.

Mode 2: localStorage

图片描述

In HTML5, a new localStorage feature has been added. this feature is mainly used as localStorage, which solves the problem of insufficient cookie storage space. the general browser in localStorage supports a size of 5M, which is different in different browsers.
The API of localStorage is also very simple, providing JS with read and write operations.

if(!  window.localStorage){
Alert ("browser does not support localstorage");
return false;
}else{
var storage = window.localStorage;
//write field a through attribute
storage.a = 1;
//write field b through the method
storage.setItem("b",2);

storage.getItem("a");
storage.b;
storage.clear();
}

It also has an advantage over cookie, providing onstorage and storage events, and can bind a callback function, using the following:

window.onstorage = function(e){console.log(e)}
//or
window.addEventListener('storage', function(){ console.log(e)})

LocalStorage is an instance of a Storage object. Any modification to the Storage object will trigger the storage event. This event is triggered when data is saved through the property or the setItem () method, deleted using the delete operator or removeItem (), or the clear () method is called. Through this event, we can monitor changes between page cards.

Implementation principle:

The list page monitors the data changes of localStorage through storage.
List page code:

<script>
window.addEventListener("storage",function(event){
console.log("newValue is"+localStorage.getItem("tid"));
console.log("oldValue is"+event.oldValue);
Window.alert ('data update!'  );
},false);
</script>

When the detail page has data modification, write it into localStorage
Details page code:

<input id="content" type="text"/>
<button id="btn">Click</button>
<script>
window.onload=function(){
var oBtn=document.getElementById("btn");
var oInput=document.getElementById("content");
oBtn.onclick=function(){
var val=oInput.value;
localStorage.setItem("tid",val);
}
}
</script>

However, onstorage and storage events will only be triggered when localStorage is modified for non-current pages. modifying localStorage for current pages will not trigger the listening function. Also, it will only be triggered when the value of the original data is modified. For example, there is already a localStorage with a key of A and a value of 1 before executing the code: localStorage.setItem(‘a’, 1), which will also not trigger the listening function.

LocalStorageinsufficient

1. The capacity of browsers is not uniform (much larger than cookie), and this attribute of localStorage is only supported in higher versions of browsers.
2. At present, all browsers limit the value type of localStorage to string type, requiring JSON conversion.
3. localStorage is essentially a reading of strings. If there is a lot of storage content, it will consume memory space and cause pages to become stuck.
4. localStorage can only monitor data changes of non-self pages, which seriously affects usage.

LocalStorageAdvantages

1. The problems of small cookie capacity and insufficient timeliness are solved.

Mode 3: WebSocket

图片描述

The WebSocket API is the asynchronous communication method of the next generation client-server and has been standardized by W3C. The greatest thing about the WebSocket API is that the server and the client can communicate in real time in both directions. WebSocket is not limited to Ajax (or XHR) communication, because Ajax technology requires clients to initiate requests, and WebSocket servers and clients can push information to each other. XHR is limited by domain, while WebSocket allows cross-domain communication.

Its use is very simple, as follows:

//Create a Socket Instance
 var socket = new WebSocket('ws://localhost:8080');
 
 //Open Socket
 socket.onopen = function(event) {
 //Send an initialization message
 socket.send('I am the client and I\'m listening!  ');
 //Listen for messages
 socket.onmessage = function(event) {
 console.log('Client received a message',event);
 };
 //Monitor Socket Shutdown
 socket.onclose = function(event) {
 console.log('Client notified socket has closed',event);
 };
 //Close Socket  ....
 socket.close()
 };

WebSocket provides send methods and onmessage events to send and receive data. The onmessage event provides a data attribute that can contain the Body portion of the message. The Body part of the message must be a string that can be serialized/deserialized to pass more data.

Implementation principle:

The list page listens to messages sent by socket server through onmessage
List page code:

<script>
 var socket = new WebSocket('ws://localhost:8080');
 socket.onopen = function(event) {
 socket.onmessage = function(event) {
 console.log('Client received a message', event);
 };
 };
 </script>

When the details page has data modification, the list page is notified to update the data through socket connection.
Details page code:

<input id="content" type="text"/>
<button id="btn">Click</button>
<script>
var socket = new WebSocket('ws://localhost:8080');
window.onload=function(){
var oBtn=document.getElementById("btn");
var oInput=document.getElementById("content");
oBtn.onclick=function(){
var val=oInput.value;
socket.onopen = function(event) {
//Send data type must be one of string, ArrayBuffer, Blob
Socket.send ('data update!'  );
}
}
</script>

The syntax of WebSocket is very simple, but IE10+ browser is required to support WebSocket communication. If your business needs to be compatible with IE8, 9. The industry usually uses a third-party library to solve this problem, such as Socket.IO, which uses a detection function to determine whether to establish a WebSocket connection, or an AJAX long-polling connection, or Flash, etc. it can quickly create real-time applications. Socket.IO also provides a NodeJS API, which looks very much like a browser API.

Weaknesses of WebSocket:

1. It needs the support of the server to complete the task. If the amount of socket data is relatively large, it will seriously consume the resources of the server.

Advantages of WebSocket:

1. Simple to use, flexible and powerful in function. If a WebSocket server is deployed, many real-time functions can be realized.

Mode 4: BroadcastChannel

BroadcastChannel is a broadcast channel, which is an API under window. The API is used to complete communication between different pages of the same origin. We can understand that it is a broadcasting station, and all broadcast instances will be connected to this broadcasting station (the control center in the mediator mode), so as long as the same channel value is passed in when initializing the instance, it will be connected to the same broadcast channel. Its implementation is the simplest. Many third-party JS libraries have implemented their own BroadcastChannel.

图片描述

Implementation principle:

The list page listens to messages sent from other pages via onmessage.
List page code:

//Receive Broadcast
let articleCast = new BroadcastChannel('mychannel');
articleCast.onmessage = function (e) {
console.log(e.data);
}

When there is data modification in the detail page, the data is transferred through postMessage.
Details page code:

//Create a broadcast and send it
 let listCast = new BroadcastChannel('mychannel');
 MyObj = {tid: "123", title: "changed title"};
 listCast.postMessage(myObj);

Shortcomings of BroadcastChannel:

1. The compatibility is extremely poor. It only supports the latest versions of Chrome and Firefox, and does not support IE and Safari at all.

Advantages of BroadcastChannel:

1, simple to use, single function, cross-page communication is an ideal choice.

Mode 5: SharedWorker

图片描述

SharedWorker is also a new browser API provided by HTML5, called shared worker thread. It allows multiple pages to share usage threads, and each page is linked to a port number of the shared worker thread. The page communicates with the shared worker thread through this port. At present, the operation of all Web programs is page-based, while the introduction of SharedWorker has opened up a concept of “Web program” thread in the background. And it can also interact with pages, which is equivalent to gathering all the pages together. In the example above, maintaining a WebSocket code for each page not only consumes a large number of connections, but also delays performance. These common connections are best made to be shared across domain pages. Before SharedWorker was introduced, there was no perfect cross-page communication solution.

Implementation principle

The list page listens to messages sent by SharedWoker via onmessage.
List page code:

<script>
 var s = new SharedWorker('x.js');
 s.port.onmessage = function(e){
 console.log(e.data);
 Window.alert ("data changes!"  )
 };
 s.port.start();
 </script>

When the details page has data modification, notify the list page to update the data through SharedWorker.

< input id = "content"/> < input type = "button" id = "btn" value = "send"/>
 <script>
 var s = new SharedWorker('x.js');
 btn.onclick=function(){
 s.port.postMessage(document.getElementById('content').value);
 };
 s.port.start();
 </script>

The code of shared thread x.js is also very simple. its work is bidirectional, and every page can be used to receive and send data.

//x.js
var pool = [];
onconnect = function(e) {
pool.push(e.ports[0]);
e.ports[0].onmessage = function(e){
for(var i=0;   i<pool.length;  i++)
pool[i].postMessage(e.data);
};
};

SharedWorker is like a defender running on the back end of the browser. It can be used by multiple window at the same time, but it must be ensured that these tabs are all homologous (same protocol, host and port number).

Shortage of SharedWorker:

1. The compatibility is poor. IE does not support it at all. chrome and Firefox support it perfectly. Safari partially supports it. If your business is an internal system, you can use it without considering IE.
2. API is relatively simple, complicated to configure, and still troublesome to use.

Advantages of SharedWorker:

1, powerful functions, not limited to browser communication, but also sharing data, methods and other functions. Because it is a new thread, it does not affect the main thread code business, has excellent performance, does not need the help of the server, and is a perfect cross-page communication solution.

What have we done? (Focus)

SharedWorker provides few apis and is relatively simple to use. it is still difficult to complete complicated page communication. Based on this, I have implemented a SharedWorker-based packaging library called superSharedWorker.

图片描述
It is a JavaScript framework for communication between pages. It realizes communication between browser-only page cards through shared worker. You don’t need to know shared worker, you can quickly use data transfer between pages, fast and powerful. Its advantage is that it is realized through native JS, and it does not need to rely on any JS library to realize the encapsulation of sharedWorker. Out of the box, the configuration is simple.

Two usage modes:
1, ES6 import way

import superSharedWorker from './src/index.js';
let superSharedWorker = new superSharedWorker('page1', callback);  //register
superSharedWorker.send('hello world!'  );  //Send message

2. Form of script Label Outer Chain

<script src="./build/super-sharedworker.js"></script>
<script type="text/javascript">
//<!  --
var superSharedWorker = new SuperShared('page1', onRecvMsg);
function onRecvMsg(message) {
console.log(message)
}
superSharedWorker.send('hello, world');
//-->
</script>

More examples of usage:

let superSharedWorker = new superSharedWorker('page1', callback);  //register
 superSharedWorker.add({name:'chunpengliu', sex:1});
 superSharedWorker.del('sex');  //Delete buffer data
 superSharedWorker.send({'time':2019}, 'page2');  //send buffer data at one time, only to the page name="page2 "
 superSharedWorker.close();  //Close threads to save resources

It provides many powerful functions to send messages one to one and one to many. Pass data like git.

Summary

Through discussion, four kinds of communication between browser tabs are realized, namely using cookie, using websocket protocol, using localstorage, and using html5 browser’s new feature SharedWorker. each method has its own advantages and disadvantages. If you don’t consider compatibility with old browsers, superSharedWorker may be the best solution, optimize usage efficiency, improve user experience, and quickly use the browser’s multi-tab communication function.

Finally,TNFE teamFor front-end developers, the latest high-quality content in small programs and web front-end technologies has been compiled. It is updated weekly. Welcome to star, github address:https://github.com/Tnfe/TNFE-Weekly

Author: TNFE Dapeng elder brother