Micro service recently looking at things and see about communication and data sharing between multiple micro service page solutions, found some relatively unfamiliar API, a strange actually take out specifically can also tell me things, also know what is, but is not skilled, can want to out of thin air is hard to think of, look at the feel some doorways, So I just expanded and sorted it out

BroadcastChannel

Broadcast also means “to Broadcast”, to Broadcast signals so that others can hear them.

This API allows all Windows, iFrames, and so on under the same original domain and user agent to interact, which is homologous communication. That is, if a user opens two tabs on the same site, both tabs will be notified of updates if the site content changes.

For example, A user opens several pages of A website at the same time and logs in on one page. Then, other pages can receive the login status from page A through BroadcastChannel, so that multiple pages can automatically synchronize the login status.

// page A broadcasts signals outward
// Create handle
const cast = new BroadcastChannel('mychannel')
// Data can be any JS data type
const data = 'I\'m from Page A'
// Broadcast signal
cast.postMessage(data)
// Close the connection
cast.close()
Copy the code
// page B listens for "broadcast" from all pages of the same origin.
// BroadcastChannel must be the same as the broadcast source you want to listen on
const cast = new BroadcastChannel('mychannel')
// Receive signal
cast.onmessage = function (e) {
  console.log(e.data) // => I'm from Page A
}
// Close the connection
cast.close()
Copy the code

BroadcastChannel is a BroadcastChannel that can send and receive signals to each other as long as it is BroadcastChannel. However, browser support is not very good, and there is no progress in it. I always feel like I’m gonna burp my ass one day

postMessage

otherWindow.postMessage(message, targetOrigin, [transfer]);

PostMessage is a much happier version of BroadcastChannel. It supports cross-domain communication, and browser support has surpassed BroadcastChannel’s to the point of being fully available in production environments. This shows that browser manufacturers are still very keen on this. There’s nothing wrong with capital driving technology

Page A obtains the handle of page B through window.open, sends A signal to page B, and listens for the signal returned by page B

<! -- page A -->
<div id="msg"></div>
<script>
  window.onload = (a)= > {
    // Get the handle
    var opener = window.open('http://127.0.0.1:9001/b.html')
    // setTimeout is to wait until the opener handle is actually obtained before sending data
    setTimeout((a)= > {
      // Only send data signals to pages whose domain name is http://127.0.0.1:9001
      opener.postMessage('red'.'http://127.0.0.1:9001');
    }, 0)
    // listen for the data signal sent back from the clause handle page
    window.addEventListener('message', event => {
      if(event.origin === 'http://127.0.0.1:9001') {document.getElementById('msg').innerHTML = event.data
      }
    })
  }
</script>
Copy the code

Page B receives the signal from page A and sends the data signal back to page A through the event handle

<div id="box">color from a.html</div>
<script type="text/javascript">
  window.addEventListener('message', event => {
    // Determine the message source address using the origin attribute
    // Only if the data signal comes from the server at http://127.0.0.1:9001
    if(event.origin === 'http://127.0.0.1:9001') {// Get the data signal of the operator
      document.getElementById('box').style.color = event.data
      // Send data back to the source via event.source
      event.source.postMessage('got your color! ', event.origin)
    }
  })
</script>
Copy the code

PostMessage is also relatively easy to use. It is important to note that the API can communicate across domains, and the greater the capability, the greater the responsibility, so there are security issues involved. Generally, when sending and receiving signals, you need to specify the signal source to avoid security issues

In contrast to BroadcastChannel, a postMessage signal is somewhat limited in that it must have a reference to another window in order to continue operations. The source of this reference can be the contentWindow property of iframe, the window object returned by executing window.open, or the window.frames named or numerically indexed. A channel number is not as flexible as an BroadcastChannel

SharedWorker

Web workers are divided into two types: dedicated Web workers and shared Web workers

The Dedicated Web worker ends when the current page closes; This means that a Dedicated Web worker can only be accessed by the page that created it; The corresponding Shared Web worker can be accessed by multiple pages (including multiple tabs and IFrames), but these pages must be homologous, that is, Shared Web workers support homologous communication

Here is a SharedWorker

// worker.js
// Shared data
let shareData = 0
// listen for connections to the main thread
onconnect = function(e) {
  const port = e.ports[0]
  port.onmessage = function(e) {
    if (e.data === 'get') {
      // Send a signal to the main thread of the connection
      port.postMessage(shareData)
    } else {
      // Set the data sent by the main thread to the shared data in the worder
      shareData = e.data
    }
  }
}
Copy the code

Set data fields in SharedWorker on page A

<input type="text" id="textInput" />
<input type="button" value="Set up shared Data" />

<script>
  const worker = new SharedWorker('worker.js')
  const inputEle = document.querySelector('#textInput')

  inputEle.onchange = (a)= > {
    console.log('Message posted to worker')
    // Send a data signal to the worker
    worker.port.postMessage(inputEle.value)
  }
</script>
Copy the code

B page to obtain data fields in SharedWorker

<div id="result"></div>
<button id="btn">Get the shared data in the SharedWorker</button>
<script>
  const worker = new SharedWorker('worker.js')
  var result = document.querySelector('#result')
  // Send a request to get the shared data in the SharedWorder
  document.getElementById('btn').addEventListener('click', () = > {// Send signals to the worker
    worker.port.postMessage('get')})// Receive shared data sent from SharedWorder
  worker.port.onmessage = e= > {
    console.log('Message received from worker')
    // Display the obtained worker share data on the page
    result.textContent = e.data
  }
</script>
Copy the code

Eventually, the values set on page A are retrieved by page B

The worker.js file is loaded separately by page A and page B, but it can share data, similar to the singleton mode. Although the new operator is used, the last two pages get the same thing

Before, I was not familiar with this SharedWorker. I only knew what it was used for, but I didn’t know the details. I always thought it could send signals in one page and receive them automatically in another page, just like BroadcastChannel or postMessge. It’s like two people on the phone, one person talking, the other person doing everything they need to do to hear it right away, and now when they’re done they realize that’s not the case

B page can access to A page set of data, but this is need to take the initiative to operation, not like A phone call, like storage, A page saved A data in public area, want to another page, need to take the initiative to go to get, I am feeling this thing may not be suitable for the page, of course, SharedWorker is not meant to be used for page communication, so it’s understandable that it doesn’t have the desired effect

In addition, when testing SharedWorker, I encountered several pits, which are mentioned here:

  • The worker.js script will be cached

When the page loads worker.js for the first time, modify the worker.js file later and refresh the page, it will be found that the worker.js file has not changed and the previous one is still modified. This is because the worker.js file is cached by the browser, and it is useless to force refresh the browser

One solution is to hash the worker.js file, for example:

const worker = new SharedWorker('worker.js? hash=v1')
Copy the code
  • The loadedworker.jsAll names must be consistent

According to the above method, the page can update worker.js, but it should also be noted that if the new worker from page A and page B (or more pages) is the same, that is to say, the data can be shared, then the worker.js loaded by these pages not only needs to be the same file, The full name must be identical, including the hash value

In the following case, page A and page B cannot share data, because they load different worker.js hash values, and the singleton mode cannot be established:

// The hash value of page A is V111
const worker = new SharedWorker('worker.js? hash=v111')
// ...

// B page, the hash value is V222
const worker = new SharedWorker('worker.js? hash=v222')
Copy the code

Compared with dedicated Web workers, the browser support of shared web workers is obviously weaker, perhaps because there are more application scenarios of dedicated Web workers than shared web workers. In addition, Microsoft’s Internet Explorer browser and Edge do not support this feature at all, as Microsoft considers the API to be a security issue and is unlikely to support it in the future

Local Storage

Local Storage is used to store data, but because the event Storage exists, it can also monitor the Storage status, so as to achieve the goal of inter-page communication

/ / A page
window.onstorage = function(e) {
  console.log(e.newValue); // previous value at e.oldValue
};
/ / B page
localStorage.setItem('key'.'value');
Copy the code

At the beginning, I always thought that the same page can monitor their own storage events, but it didn’t work for a long time. I also searched the MDN document for several times but didn’t find out the reason, and then I finally found the reason on the Internet. The same page cannot listen to its own storage event (like FireFox can listen to its own? It’s almost impossible to write a string that supports page to page communication

websocket

WebSocket is a protocol for full duplex communication on a single TCP connection provided by HTML5. The common scenario is instant communication

To use this technology, both the browser and server must support node.js’s WebSocket solution, known as socket.io

The server side

// index.js
const server = require('http').createServer()
const io = require('socket.io')(server)

io.on('connection', socket => {
  socket.on('clientMsg', data => {
    // Broadcast is directly broadcast to all connections except the sender
    socket.broadcast.emit('serverMsg', data)
  })
})
server.listen(3000)
Copy the code

IO package, so remove other unnecessary logic, the main function is to open a socket connection, can receive and broadcast messages, similar to a chat room server

Client code:

<! -- client.html -->
<! -- Message list -->
<ul id="ul"></ul>
<input type="text" id="textInput" />
<button onclick="btnClick()">send</button>
<script>
  const socket = io('http://localhost:3000')
  // Receive the message sent by the server
  socket.on('serverMsg', data => {
    addLi(`${data.id}: ${data.msg}`)})const ul = document.getElementById('ul')
  const textInput = document.getElementById('textInput')
  const id = new Date().getTime()
  
  // Send a message to the server
  function btnClick() {
    socket.emit('clientMsg', { msg: textInput.value, id })
    textInput.value = ' '
  }
  function addLi(text) {
    const li = document.createElement('li')
    li.innerText = text
    ul.appendChild(li)
  }
</script>
Copy the code

In order to cooperate with the server side, we need to introduce the socket.io. Js file on the page to enable the websocket on the browser side:

<script src="https://cdn.bootcss.com/socket.io/2.1.1/socket.io.js"></script>
Copy the code

After the socket. IO server is started, the client page client. HTML is opened locally, and several more tabs are opened. Each client. HTML is a message receiver

Websocket technology is very mature, can be used in production environment, in addition to a little learning cost, it is not difficult to use, there are no restrictions on the use of a wide range of scenarios, but if it is only page to page communication, using this thing seems to be a bit of a dead end. After all, a dedicated Websocket server can’t run away anyway, right

indexDB

Like LocalStorage, indexDB is used for data storage, but more “specialized”

IndexedDB is a low-level API used to store large amounts of structured data (including files and blobs) on clients. The API uses indexes to perform high-performance searches for this data. Unlike LocalStorage, which stores only strings, IndexedDB can store all types of JS data. Including null, undefined, etc., is a new API in the HTML5 specification

IndexedDB is a way to store large amounts of data using a browser. It creates data that can be queried and used offline. IndexedDB is an effective solution for applications that need to store large amounts of data or that need to be used offline

const request = indexedDB.open('dbBox')
request.onsuccess = function(e) {
  console.log('Successfully opened IndexDB')
  const myDB = e.target.result
  // Start a read-write thing
  const transaction = myDB.transaction('person'.'readwrite')
  // Get the handle to the person table
  const store = transaction.objectStore('person')
  // Add two pieces of data to the person table
  store.add({name: 'jane'.email:'[email protected]'})
  store.add({name: 'kangkang'.email:'[email protected]'})
  // All data added successfully, triggering the transaction onComplete event
  transaction.oncomplete = function(event) {
    // Restart a query transaction
    const getResult = myDB.transaction('person'.'readwrite').objectStore('person').get('jane')
    getResult.onsuccess= e= > {
      console.log('Query result:', e.target.resule)
      // => {name: 'jane', email:'[email protected]'}}}}// This event is triggered when the database is opened for the first time or the database version is updated
request.onupgradeneeded = function(e) {
  const db = e.target.result
  // If the person table does not exist
  if(! db.objectStoreNames.contains('person')) {
    // Create a new table person
    const objectStore = db.createObjectStore('person', {
      // specify a primaryKey, similar to a primaryKey, that is used for subsequent database lookups
      keyPath: "name"
    })
    // Create table field name
    objectStore.createIndex("name"."name", {
      // Specify a field that can be indexed. The unique field is used to specify whether it is unique
      unique: true
    })
    // Create table phone
    objectStore.createIndex("phone"."phone", {
      unique: false}}})Copy the code

The simple examples above, which include connecting to a database, creating a table, creating a table field structure, adding data, querying data, and so on, are clearly annotated without further explanation

Once done, F12 opens the browser’s console, selects the Application TAB, selects IndexeddDB, and expands to see the stored data

IndexDB as local storage API, there is no global monitoring events, so I can’t for the page, but can be used for data sharing, the API more exclusive terms and concepts involved, may be not so good for the front end of the pure understanding, but as long as it is the computer professional background, for the basic concept of database is able to understand, Essentially nothing, just a simplified version of a local database, right

For indexedDB, browser desktop support is good

webSql

IndexedDB is also a browser database. IndexedDB can be considered as a NoSql database. The operation instructions (add, delete, change, query, etc.) are called in a more “front-end” way, whereas Web SQL is more like a relational database. Examples such as mysql, SQL Server, etc. are more like it, and Web SQL is more like a database than IndexexDB

In addition, the Web SQL database API is not part of the HTML5 specification, but it is a separate specification that introduces a set of APIs for manipulating client databases using SQL. Strangely, though, this stuff doesn’t seem to be persistent storage. After a page refresh, previously stored data, Including database, data table completely drop

// Open a database named mydb, create it if it does not exist, specify the version number as 1.0, the description text of the database as Test DB, and limit the size to 2 * 1024 * 1024
var db = openDatabase('mydb'.'1.0'.'Test DB'.2 * 1024 * 1024)
var msg
// Start the transaction
db.transaction(function (tx) {
  // Create a table named LOGS with id and log fields
  tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)')
  // Insert two pieces of data into the table
  tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, 2)')
  tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "www.runoob.com")')})// Start transaction
db.transaction(function (tx) {
  // Query all data from LOGS table
  tx.executeSql('SELECT * FROM LOGS'[],function (tx, results) {
    const len = results.rows.length
    // Format the result of the query
    const rst = Array(len).fill(1).map((v, index) = > results.rows.item(index))
    console.log('The list of queried data is:', rst)
  }, null)});Copy the code

After doing this, F12 opens the browser’s console, selects the Application TAB, selects Web SQL, and expands to see the stored data

As you can see, there is a lot of SQL in this operation, which is equivalent to learning another SQL language for people who are not familiar with databases. Although it is not difficult to learn basic usage, it is not friendly to front-end programmers. In addition, relational databases appear in the world of JavaScript, which is extremely flexible. There seems to be an incongruity, so the verdict on Web Sql is this:

IndexedDB is an alternative to WebSQL, which was scrapped by the W3C on November 18, 2010. IndexedDB differs from WebSQL in that WebSQL is a relational database (complex) and IndexedDB is a key-value database (simple and efficient).

Before I read this sentence, I thought WebSql was more advanced and IndexedDB should be replaced. However, life is full of surprises

conclusion

Just from the knowledge of micro services to see a point, expansion is an article, really is to learn endless ah. In college, before is more time every day, so happily every day in learning, and come out to learn a new knowledge, joy, now work, every business code written not over, but still need to find time to learn new knowledge, focus on a huge pile of technology, public articles finish see all look not to push every day, The more I know about technology, the more I feel that technology is endless, and I just want to say, please don’t make anything new, I can’t learn anymore and I’m never too old to learn.