同源多页面实时通信之BroadcastChannel实现及简单封装

news2024/11/24 14:46:59

目录

  • 背景
  • 介绍及API使用
    • 是什么
    • 对象实例化
    • 发送消息
    • 监听消息
    • 错误处理
    • 关闭通道
  • 项目中简单封装
    • channel.js文件,引入到使用的页面中
    • 发送端send.html
    • 监听端
    • 运行测试一下吧
  • 浏览器兼容程度
  • 总结

背景

日常开发做项目时,如果采用非Vue脚手架时,肯定会碰到这样的场景:比如在浏览器中新开两个tab页面,A页面发送消息后,B页面实时监听并触发某些动作。类似的需求有很多,比如实时共享状态等等。这样的实时通信场景的解决方案我相信大家有很多想法,比如localStoragepostMessageWebSocketsharedWorker等等。
今天带来另一种方式:BroadcastChannel广播通信。如果着急,可直接跳转到“项目中简单封装章节查看封装代码”

介绍及API使用

是什么

BroadcastChannel 接口代理了一个命名频道,可以让指定 origin 下的任意 browsing context 来订阅它。它允许同源的不同浏览器窗口,Tab 页,frame 或者 iframe 下的不同文档之间相互通信。通过触发一个 message 事件,消息可以广播到所有监听了该频道的 BroadcastChannel 对象。

简单来说,就是需要在同源的情况下,实现浏览器多窗口实时进行通信,且该通信是广播进行的。

对象实例化

// 通道名称,用以区分不同的通道。对于相同的来源下的所有浏览上下文,一个名称只对应一个通道。是string类型,用来标识当前的BroadcastChannel
const channel = new BroadcastChannel(channelName)

发送消息

可以使用postMessage() 发送一条消息,给所有同源下监听了该频道的所有浏览器。消息message事件的形式发送给每一个绑定到该频道的广播频道。

 
const channel = new BroadcastChannel("test")
 
// 发送消息通知,参数是任何对象
bc.postMessage('hello xiaozong');

监听消息

发送事件后,如何使用进行消息的监听呢?当频道收到一条消息时,会在关联的BroadcastChannel对象上触发 message 事件,监听方式有两种,具体如下:

const channel = new BroadcastChannel("test")
// 消息监听 方式一
channel.onmessage = ({data}) => {
	// 这里写具体的业务逻辑
}
 
// 消息监听 方式二
channel.addEventListener('message', ({data}) => {
	// 这里写具体的业务逻辑
})

错误处理

const channel = new BroadcastChannel('test');
 
// 方式一
channel.addEventListener('messageerror', ({data}) => {
  console.error(data);
})
 
// 方式二
channel.onmessageerror = ({data}) => {
  console.log(data);
};

关闭通道

通过调用 close() 方法,可以马上断开其与对应频道的关联,并让其被垃圾回收。这是必要的步骤,因为浏览器没有其他方式知道频道不再被需要。不断开可能会导致一直处于监听状态,消耗资源,会导致不能被内存回收。

// 连接到指定频道
const channel = new BroadcastChannel('test');

// 当完成后,断开与频道的连接
channel.close();

项目中简单封装

channel.js文件,引入到使用的页面中

/**
 * 简单封装BroadcastChannel的用法
 */
const Channel = {
    /**
     * BroadcastChannel对象
     */
    channel: null,

    /**
     * 实例化BroadcastChannel对象,赋值给channel变量
     * @param {*} channelName 通道名称,用以区分不同的通道
     * @returns 
     */
    getChannel: (channelName) => {
        Channel.channel = new BroadcastChannel(channelName)
        return Channel.channel
    },

    /**
     * 发送消息
     * @param {*} object 消息体
     */
    send: (object) => {
        Channel.channel.postMessage(object)
    },

    /**
     * 发送消息,重载方法,可直接调用,省略对象实例化操作
     * @param {*} channelName 通道名称,用以区分不同的通道
     * @param {*} object 消息体
     */
    send: (channelName, object) => {
        if (Channel.channel == null) {
            Channel.channel = Channel.getChannel(channelName)
        }
        Channel.channel.postMessage(object)
    },

    /**
     * 监听消息
     * @param {*} callback 回调函数
     */
    listen: (callback) => {
        Channel.channel.onmessage = ({ data }) => {
            callback(data)
        }
    },

    /**
     * 监听消息,重载方法,可直接调用,省略对象实例化操作
     * @param {*} channelName 通道名称,用以区分不同的通道
     * @param {*} callback 回调函数
     */
    listen: (channelName, callback) => {
        if (Channel.channel == null) {
            Channel.channel = Channel.getChannel(channelName)
        }
        Channel.channel.onmessage = ({ data }) => {
            callback(data)
        }
    },

    /**
     * 通道关闭
     */
    close: () => {
        Channel.channel.close()
    },

    /**
     * 通道关闭,重载方法,可直接调用,省略对象实例化操作
     * @param {*} channelName 通道名称,用以区分不同的通道
     */
    close: (channelName) => {
        if (Channel.channel == null) {
            Channel.channel = Channel.getChannel(channelName)
        }
        Channel.channel.close()
    },

    /**
     * 通道枚举,定义业务中需要用到的所有通道名称枚举,可根据业务需求无限扩容
     */
    channelEnum: {
        TEST: { name: 'test', coment: '测试通道' },
        REAL_EVENT: { name: 'real_event', coment: '实时事项通道' },
    }
}

发送端send.html

使用方式测试如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>标签页通信-发送端</title>
    <script src="./channel.js"></script>
</head>

<body>
    标签页通信-发送端
</body>
<script>
    Channel.send(Channel.channelEnum.TEST.name, 'hello xiaozong')

</script>

</html>

监听端

使用方式测试如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>标签页通信-接收端</title>
    <script src="./channel.js"></script>
</head>

<body>
    标签页通信-接收端
</body>
<script>
    Channel.listen(Channel.channelEnum.TEST.name, (data) => {
        document.write(`<p>${data}</p>`)
    })
</script>

</html>

运行测试一下吧

就只贴一下图吧 ,比较简单
在这里插入图片描述
在这里插入图片描述

浏览器兼容程度

在这里插入图片描述

总结

昨晚十二点左右心血来潮,太晚了也只进行了简单的封装,基本满足常规场景的使用,如果实际项目开发中有用到的话,可以优化后使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1090978.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[开源]企业级流程中心,基于flowable和bpmn.js封装的流程引擎

一、开源项目简介 企业级流程中心&#xff08;基于flowable和bpmn.js封装的流程引擎&#xff0c;采用Springboot&#xff0c;Mybatis-plus, Ehcache, sa-token 等框架技术,前端采用Vue3&Antd&#xff0c;Vben&#xff09;。 二、开源协议 使用Apache-2.0开源协议 三、界…

[计算机进阶] 用户和用户组

1.1 用户和用户组 1.1.1 用户 用户账户是计算机操作系统中用于标识和管理用户身份的概念。 每个用户都拥有一个唯一的用户账户&#xff0c;该账户包含用户的登录名、密码和其他与用户身份相关的信息。 用户账户通常用于验证用户身份&#xff0c;并授权对系统资源的访问权限。…

C++的指针简明教程

C的指针简明教程 指针是C和C语言中非常重要的概念&#xff0c;初学的时候会被指针搞蒙。想学好指针&#xff0c;我的经验是不要试图一开始就想理解指针概念&#xff0c;而是要耐心准确的了解指针的各个方面&#xff0c;这是一个过程&#xff0c;随着学习的深入&#xff0c;自然…

【算法-动态规划】最长公共子串

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

2023年中国点式光纤传感器产量、需求量及行业市场规模分析[图]

点式光纤传感器也称为分立式光纤传感器。点式传感器的技术原理是通过识别某点的干涉效应的改变来探测信号&#xff1b;准分布式传感器则是在点式传感器的基础上重复&#xff0c;实现多点同时探测&#xff0c;按所使用传感单元数量的不同&#xff0c;点式光纤传感技术又可分为单…

ModuleNotFoundError: No module named ‘requests‘

目录 一、遇到问题 二、原因 三、问题解决&#xff1a; 1.pycharm中 2.Linux系统中 一、遇到问题 ModuleNotFoundError: No module named requests 二、原因 ModuleNotFoundError&#xff1a;没有名为“requests”的模块 三、问题解决&#xff1a; 1.pycharm中 File--Sett…

多测师肖sir_高级金牌讲师_python之函数007

python之函数 一、什么是函数 &#xff08;1&#xff09;定义&#xff1a;函数是组织好的&#xff0c;可重复使用的&#xff0c;用来实现单一&#xff0c;或相关联功能 的代码段。 &#xff08;2&#xff09;python的结构&#xff0c;&#xff08;函数写在.py文件下&#xff0…

Idea执行Pom.xml导入jar包提示sun.misc.BASE64Encoder jar找不到---SpringCloud工作笔记197

奇怪之前都是好好的,这个是因为,jdk的版本不对,重新打开以后自动被选择成jdk11了...记录一下 原因是从jdk9的时候,这个jar包已经被删除了,所以会报错,如果你用的是jdk自带的这个jar包就会报错,那么还可以,修改,不让他用jdk的,让他用 用org.apache.commons.codec.binary.Base64…

如何处理前端异步操作(Promises、async/await等)?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

JWT - 令牌认证授权(认证流程、认证原理、Jwt 工具类)

目录 一、JWT 认证 1.1、对 JWT 的认识 1.1.1、JWT 解释 1.1.2、为什么使用的 JWT 认证&#xff0c;而不是 Session 认证&#xff1f; a&#xff09;基于传统的 Session 认证 1.1.3、JWT 认证流程 1.1.4、优势 1.1.5、JWT 的结构 JWT 第一部分&#xff1a;标头 Header …

python+django高校体育乒乓球场地预约管理系统_s2409

本系统提供给管理员对首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;乒乓球场管理,场地类型管理,场地预约管理,暂离申请管理,离开申请管理,管理员管理,留言反馈,系统管理等诸多功能进行管理。本系统对于用户输入的任何信息都进行了一定的验证&#xff0c;为管理员操…

Altium Designer实用系列(四)----Ultra Librarian 下载芯片原理图库及封装并导入AD

一、 原理图库的下载 本篇博客讲解的方法适合特殊封装的芯片&#xff0c;如果是普通封装&#xff0c;直接使用现成的库即可。本篇博客以TI的芯片MCT831举例&#xff1a;    首先是去TI官网找到该芯片的详细页面&#xff1a; 然后在“设计和开发”页面中找到CAD/CAE符号&…

2023年中国玉米深加工产能、市场规模、消费量及产品需求结构[图]

玉米深加工顾名思义就是将产业链延长,进而提升产品附加值,利用玉米提炼出酒精、玉米胚芽油、淀粉和饲料等大概两百余种玉米深加工产品。我国是玉米种植大国&#xff0c;也是玉米深加工大国&#xff0c;但是玉米加工行业却长时间处于产能过剩、开工率不足、利润率低下的境况&…

兄弟MFC-7480D打印机墨粉清零方法(图解)

兄弟MFC-7480D更换新的墨粉盒或者加墨粉后还是提示更换墨粉盒&#xff0c;这个时候就需要进行清零处理了&#xff0c;现将清零的小方法分享给大家&#xff0c;希望能够帮助到大家&#xff1b; 具体清零方法如下&#xff1a; 1、首先打开打印机前盖&#xff0c;按住【OK】键3秒左…

Ubuntu - 连接 ssh 网络错误

0、问题 1、解决 1.1 可能问题&#xff1a;网络问题(是否 ping 通) Ubuntu有网 1.2、可能问题&#xff1a;SSH 服务未运行 列出当前正在监听的网络连接 ss -tln可见没有22端口被监听&#xff0c;那应该就是没有运行 SSH 服务 1.2.1、确保 OpenSSH Server 已安装 大多数…

opencv图形绘制2

目录 制作宣传语&#xff08;中文&#xff09; 制作宣传语&#xff08;英文&#xff09; 绘制标记 鼠标交互绘制十字线 鼠标交互绘制图形 鼠标交互制作几何画板 滚动条控制 制作宣传语&#xff08;中文&#xff09; import cv2 import numpy as np from PIL import Image…

pytest+allure生成测试报告

pytest框架使用 一、安装插件 #常用安装插件 pytest pytest-html &#xff08;生成html格式的自动化测试报告&#xff09; pytest-xdist &#xff08;测试用例分布式执行&#xff0c;多cpu分发&#xff09; pytest-ordering&#xff08;用于改变测试用例的执行顺序&#xff0…

有趣的 scanf()

限制接收内容 这里的意思是直接收a、b、c作为ch的内容&#xff0c;遇到其它字符放入缓冲区中。 【scanf("%[...]",ch);只接收[]中的内容作为字符串的内容,将其它的内容放入缓冲区中】 这里将aaa后面的h放入缓冲区&#xff0c;但是没有抛弃掉&#xff0c;故而无法接收…

实现手机号码中间四位显示为*号方法

实现手机号码中间四位显示为*号方法&#xff1a; substring使用方法&#xff1a; 开始位置&#xff0c;结束位置&#xff08;不包括结束&#xff09; 下面的示例就是 截取0到3不包含3&#xff0c;中间4个*&#xff0c;从第7开始截取到最后 // 转换用户手机号let telephone t…

GPU -- 图形处理器(显卡)

目录 GPUGPU 的主要信息和功能显存位宽接口v-sync散热 GPU 显卡&#xff08;Graphics Processing Unit&#xff0c;GPU&#xff09;是计算机中的一种专门用于处理图形和图像相关任务的硬件设备。它是计算机图形和图像处理的关键组成部分&#xff0c;通常用于加速图形渲染、视频…