This is the 22nd day of my participation in Gwen Challenge. See more details: Gwen Challenge!
Introduction to 👽
As we all know, different tabs in the same browser cannot communicate directly with each other due to the security policies of the browser. The simplest and most reliable bridge for indirect communication is LocalStroage.
LocalStroage is a solution for local storage in browsers. The main difference between LocalStroage and SessionStroage is that it is not limited by TAB page isolation and can share storage content as long as it is in the same state.
👽 Basic Ideas
The basic idea is simple: globally add a listener that listens to localStroage and responds when the value in localStoage changes on the target page.
The principle is very simple, the specific implementation of our analysis by this principle lsbridge library source code, see there is no more worth learning.
👽 Lsbridge source code interpretation
//lsbridge https://github.com/krasimir/lsbridge
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define([], factory);
} else if (typeof exports= = ='object') {
module.exports = factory();
} else {
root.lsbridge = factory();
}
})(this.function () {
var api = {};
/** * -- Test lsBridge compatibility -- * But this step is not very necessary, * currently there are few browsers that do not support LsBridge */
api.isLSAvailable = (function () {
var mod = '_';
try {
localStorage.setItem(mod, mod);
localStorage.removeItem(mod);
return true;
} catch (e) {
return false;
}
})();
if (api.isLSAvailable) {
var interval = 100.The library actually listens by constantly accessing localStroge.
intervalForRemoval = 200.// Clear the interval
ls = localStorage,
listeners = {}, // Listener (all subscribed messages will be on this object)
isLoopStarted = false,
buffer = {}; // cache (for data transfer)
/ * * * *@description This method is the key to listening to localStroge on a regular basis. * This method takes the values of each namespace from the listener, puts them into the cache, performs the corresponding custom methods on the data, and emptying the cache */
var loop = function () {
console.log('buffer: ', buffer);
for (var namespace in listeners) {
var data = ls.getItem(namespace);
if (data && buffer[namespace] && buffer[namespace].indexOf(data) === -1) {
buffer[namespace].push(data);
try {
var parsed = JSON.parse(data);
if (parsed) data = parsed;
} catch (e) {}
for (var i = 0; i < listeners[namespace].length; i++) {
listeners[namespace][i](data);
}
if(! ls.getItem(namespace +'-removeit')) {
ls.setItem(namespace + '-removeit'.'1');
(function (n) {
setTimeout(function () {
ls.removeItem(n);
ls.removeItem(n + '-removeit'); buffer[namespace] = []; }, intervalForRemoval); })(namespace); }}else if (!data) {
buffer[namespace] = [];
}
}
console.log('buffer: ', buffer);
setTimeout(loop, interval);
return true;
};
/ * * *@description Call this method to publish a message * to the target namespace@param {*} Namespace Specifies the target namespace (which can be seen as the key of the localstorage key/value pair) *@param {*} Data message content (which can be seen as value in a key-value pair in localstorage) *@supplement This method takes special care of the message content in the form of a function or object and stores it in the corresponding localStroge namespace */
api.send = function (namespace, data) {
var raw = ' ';
if (typeof data === 'function') {
data = data();
}
if (typeof data === 'object') {
raw = JSON.stringify(data);
} else {
raw = data;
}
ls.setItem(namespace, raw);
};
/ * * *@description Call this method to subscribe to the target namespace *@param {*} Namespace Target namespace *@param {*} Cb Indicates a user-defined method *@supplement // If the target namespace exists (if it does not, create a new namespace on both the listener and the cache). * will store the corresponding execution method in the listener, and start the timer */
api.subscribe = function (namespace, cb) {
if(! listeners[namespace]) { listeners[namespace] = []; buffer[namespace] = []; } listeners[namespace].push(cb);if (!isLoopStarted) {
isLoopStarted = loop();
}
};
/ * * *@description Call this method to unsubscribe *@param {*} Namespace Target namespace *@supplement Release listeners and caches when unsubscribe */
api.unsubscribe = function (namespace) {
if (listeners[namespace]) {
listeners[namespace] = [];
}
if(buffer[namespace]) { buffer[namespace] = []; }}; api.getBuffer =function () {
return buffer;
};
} else {
api.send = api.subscribe = function () {
throw new Error('localStorage not supported.');
};
}
return api;
});
Copy the code