JS SharedWorker detailed introduction/broadcasting/Vue use

1. Introduction to SharedWorker

SharedWorker is a kind of Worker, the Chinese name is "shared thread", which is mainly used for sharing threads and data between pages of the same origin, and is often used for communication between different tab pages of browsers.

If you don't know Worker yet, you can check here .

2. Use of SharedWorker

1. Compatibility

ie does not support, chrome fully supports
Compatibility judgment:if (!SharedWorker) { throw new Error('当前浏览器不支持SharedWorker') }
insert image description here

2. Create

  1. Create a shared thread js file: SharedWorker.js
  2. Create a shared threadconst worker = new SharedWorker('SharedWorker.js')
  3. Every time a worker is created, if the parameter url is the same, it will be regarded as using the same shared thread, and the shared thread will allocate a port to distinguish different users

3. Communication

  1. Both the main thread and the shared thread postMessage()send messages through the method
  2. Receiving a message is done using onmessage = (e)=>{}, oraddEventListener('message', (e)=>{})

4. Startup and shutdown

The thread is worker.port.start()started by
the thread worker.port.close()is closed by the thread
. When using a single page application, remember to close it, otherwise it will be permanent

5. Debugging

SharedWorker cannot be viewed directly in the page debugging panel, it needs browser input chrome://inspect/#workers
and then click inspect to view
insert image description here

6. The simplest demo

The simplest demo is used here to illustrate the usage,

  • SharedWorker.js shared thread, which stores timer counter
  • page1.html Refresh the page and notify counter+1
  • page2.html Refresh the page to view the counter

6.1 SharedWorker.js code

// 计时器
let counter = 0

// 监听连接
self.addEventListener('connect', (e) => {
    
    
  const port = e.ports[0]
  port.onmessage = (res) => {
    
    
    console.log('共享线程接收到信息:', res.data)
    switch (res.data) {
    
    
      case 'counter++':
        counter++
        break
    }
    console.log('counter:', counter)
    port.postMessage(counter)
  }
})

6.2 Page1.html code

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>SharedWorker示例-页面1</title>
  </head>
  <body>
    <h1>SharedWorker示例-页面1</h1>
    <script>
      // 兼容性判断
      if (!SharedWorker) {
      
      
        throw new Error('当前浏览器不支持SharedWorker')
      }

      // 创建共享线程
      const worker = new SharedWorker('SharedWorker.js')

      // 启动线程端口
      worker.port.start()

      // 向共享线程发送消息
      worker.port.postMessage('counter++')

      // 线程监听消息
      worker.port.addEventListener('message', (e) => {
      
      
        console.log('page1页面共享线程counter值:', e.data)
      })
    </script>
  </body>
</html>

6.3 Page2.html code

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>SharedWorker示例-页面2</title>
  </head>
  <body>
    <h1>SharedWorker示例-页面2</h1>
    <script>
      // 兼容性判断
      if (!SharedWorker) {
      
      
        throw new Error('当前浏览器不支持SharedWorker')
      }

      // 创建共享线程
      const worker = new SharedWorker('SharedWorker.js')

      // 启动线程端口
      worker.port.start()

      // 向共享线程发送消息
      worker.port.postMessage('get counter')

      // 线程监听消息
      worker.port.addEventListener('message', (e) => {
      
      
        console.log('page2页面共享线程counter值:', e.data)
      })
    </script>
  </body>
</html>

6.4 Result output

insert image description here

3. Precautions for using SharedWorker

SharedWorker is an application of Worker, so the items to note are consistent with Worker

  1. The context of the shared thread is itself, which can be obtained through self or this;

  2. The message passed between the main thread and the shared thread is copied rather than shared , which means that if the passed parameter is an object, the program will use the JSON method to encode/decode the object;

  3. The main thread and the sub-thread have different contexts and different scopes. The sub-thread cannot call the dom and methods of the main thread. Specifically, it
    cannot be used :

    • window object
    • document object
    • parent object
    • alert()
    • confirm()

    You can use :

    • navigator object
    • location object (read-only)
    • XMLHttpRequest
    • setTimeout()/clearTimeout() 和 setInterval()/clearInterval()
    • application cache
    • Import external scripts using the importScripts() method
    • Spawn additional Web Workers

4. Example of Broadcasting

The above demo only demonstrates that different pages share the data of the shared thread, but refreshing page1 will not actively notify page2 of data changes, and page2 must be refreshed to obtain new data, so what if the broadcast effect is achieved?

The following demo realizes the broadcast effect, that is, the shared thread will send messages to all ports

  • SharedWorker.js shared thread, storage timer counter, counter change will notify page1 and page2
  • page1.html Refresh the page and notify counter+1
  • page2.html Refresh the page and notify counter+1

4.1 SharedWorker.js code

The core is to save all connected ports

let counter = 0 // 计时器
let ports = [] // 存储所有连接端口的数组

// 监听连接
self.addEventListener('connect', (e) => {
    
    
  const port = e.ports[0]
  // 把端口对象存起来
  ports.push(port)

  // 监听消息
  port.onmessage = (res) => {
    
    
    console.log('共享线程接收到信息:', res.data)
    switch (res.data) {
    
    
      case 'counter++':
        counter++
        break
    }
    console.log('当前counter:', counter)

    // 向所有端口广播
    ports.forEach((p) => {
    
    
      p.postMessage(counter)
    })
  }
})

4.2 Page1.html code

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>SharedWorker示例-页面1</title>
  </head>
  <body>
    <h1>SharedWorker示例-页面1</h1>
    <script>
      // 兼容性判断
      if (!SharedWorker) {
      
      
        throw new Error('当前浏览器不支持SharedWorker')
      }

      // 创建共享线程
      const worker = new SharedWorker('SharedWorker.js')

      // 启动线程端口
      worker.port.start()

      // 向共享线程发送消息
      worker.port.postMessage('counter++')

      // 线程监听消息
      worker.port.addEventListener('message', (e) => {
      
      
        console.log('page1页面共享线程counter值:', e.data)
      })
    </script>
  </body>
</html>

4.3 Page2.html code

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>SharedWorker示例-页面2</title>
  </head>
  <body>
    <h1>SharedWorker示例-页面2</h1>
    <script>
      // 兼容性判断
      if (!SharedWorker) {
      
      
        throw new Error('当前浏览器不支持SharedWorker')
      }

      // 创建共享线程
      const worker = new SharedWorker('SharedWorker.js')

      // 启动线程端口
      worker.port.start()

      // 向共享线程发送消息
      worker.port.postMessage('counter++')

      // 线程监听消息
      worker.port.addEventListener('message', (e) => {
      
      
        console.log('page2页面共享线程counter值:', e.data)
      })
    </script>
  </body>
</html>

4.4 Result output

insert image description here

Five, use in vue

5.1 Create sub-shared thread js

Create a shared thread js: 根目录/public/shared-worker/SharedWorker.js, the code is as follows:

// 计时器
let counter = 0

// 监听连接
self.addEventListener('connect', (e) => {
    
    
  const port = e.ports[0]
  port.onmessage = (res) => {
    
    
    console.log('共享线程接收到信息:', res.data)
    switch (res.data) {
    
    
      case 'counter++':
        counter++
        break
    }
    console.log('counter:', counter)
    port.postMessage(counter)
  }
})

5.2 Use of vue files

Create a vue file, the code is as follows

<template>
  <div><h1>SharedWorker使用</h1></div>
</template>

<script>
export default {
      
      
  created() {
      
      
    // 兼容性判断
    if (!window.SharedWorker) {
      
      
      throw new Error('当前浏览器不支持SharedWorker')
    }

    // 创建共享线程
    this.worker = new SharedWorker('/shared-worker/SharedWorker.js')

    // 启动线程端口
    this.worker.port.start()

    // 向共享线程发送消息
    this.worker.port.postMessage('counter++')

    // 线程监听消息
    this.worker.port.addEventListener('message', this.messageHandle)
  },
  methods: {
      
      
    // 消息处理
    messageHandle(e) {
      
      
      console.log('SharedWorker共享线程counter值:', e.data)
    },
  },
  destroyed() {
      
      
    // 记得销毁线程
    this.worker.port.removeEventListener('message', this.messageHandle)
    this.worker.port.close()
    this.worker = null
  },
}
</script>

兄弟,都看到这里了,点个赞再走呗

Guess you like

Origin blog.csdn.net/iamlujingtao/article/details/122078713