JavaScript 如何实现同源通信

目录
  • 一、Broadcast Channel API 简介
  • 二、Broadcast Channel API 应用场景
    • 2.1 实现同源页面间数据同步
    • 2.2 在其它 Tab 页面中监测用户操作
  • 三、Broadcast Channel API vs postMessage API
  • 四、总结
  • 五、参考资源

一、Broadcast Channel API 简介

Broadcast Channel API 可以实现同源下浏览器不同窗口、Tab 页或者 iframe 下的浏览器上下文之间的简单通讯。通过创建一个监听某个频道下的 BroadcastChannel 对象,你可以接收发送给该频道的所有消息。

(图片来源 —— https://developer.mozilla.org/zh-CN/docs/Web/API/Broadcast_Channel_API

了解完 Broadcast Channel API 的作用之后,我们来看一下如何使用它:

// 创建一个用于广播的通信通道
const channel = new BroadcastChannel('my_bus');

// 在my_bus上发送消息
channel.postMessage('大家好,我是阿宝哥');

// 监听my_bus通道上的消息
channel.onmessage = function(e) {
  console.log('已收到的消息:', e.data);
};

// 关闭通道
channel.close();

通过观察以上示例,我们可以发现 Broadcast Channel API 使用起来还是很简单的。该 API 除了支持发送字符串之外,我们还可以发送其它对象,比如 Blob、File、ArrayBuffer、Array 等对象。另外,需要注意的是,在实际项目中,我们还要考虑它的兼容性:

(图片来源 —— https://caniuse.com/?search=Broadcast%20Channel%20API

由上图可知,在 IE 11 及以下的版本,是不支持 Broadcast Channel API,这时你就可以考虑使用现成的 broadcast-channel-polyfill 或者基于 localStorage 和 storage 事件来实现。

二、Broadcast Channel API 应用场景

利用 Broadcast Channel API,我们可以轻易地实现同源页面间一对多的通信。该 API 的一些使用场景如下:

  • 实现同源页面间数据同步;
  • 在其它 Tab 页面中监测用户操作;
  • 指导 worker 执行一个后台任务;
  • 知道用户何时登录另一个 window/tab 中的帐户。

为了让大家能够更好地掌握 Broadcast Channel API,阿宝哥以前面 2 个使用场景为例,来介绍一下该 API 的具体应用。

2.1 实现同源页面间数据同步

html

<h3 id="title">你好,</h3>
<input id="userName" placeholder="请输入你的用户名" />

JS

const bc = new BroadcastChannel("abao_channel");

(() => {
  const title = document.querySelector("#title");
  const userName = document.querySelector("#userName");

  const setTitle = (userName) => {
    title.innerHTML = "你好," + userName;
  };

  bc.onmessage = (messageEvent) => {
    if (messageEvent.data === "update_title") {
      setTitle(localStorage.getItem("title"));
    }
  };

  if (localStorage.getItem("title")) {
    setTitle(localStorage.getItem("title"));
  } else {
    setTitle("请告诉我们你的用户名");
  }

  userName.onchange = (e) => {
    const inputValue = e.target.value;
    localStorage.setItem("title", inputValue);
    setTitle(inputValue);
    bc.postMessage("update_title");
  };
})();

在以上示例中,我们实现了同源页面间的数据同步。当任何一个已打开的页面中,输入框的数据发生变化时,页面中的 h3#title 元素的内容将会自动实现同步更新。

2.2 在其它 Tab 页面中监测用户操作

利用 Broadcast Channel API,除了可以实现同源页面间的数据同步之外,我们还可以利用它来实现在其它 Tab 页面中监测用户操作的功能。比如,当用户在任何一个 Tab 中执行退出操作后,其它已打开的 Tab 页面也能够自动实现退出,从而保证系统的安全性。

html

<h3 id="status">当前状态:已登录</h3>
<button onclick="logout()">退出</button>

JS

const status = document.querySelector("#status");
const logoutChannel = new BroadcastChannel("logout_channel");

logoutChannel.onmessage = function (e) {
  if (e.data.cmd === "logout") {
    doLogout();
  }
};

function logout() {
  doLogout();
  logoutChannel.postMessage({ cmd: "logout", user: "阿宝哥" });
}

function doLogout() {
  status.innerText = "当前状态:已退出";
}

在以上示例中,当用户点击退出按钮后,当前页面会执行退出操作,同时会通过 logoutChannel 通知其它已打开的页面执行退出操作。

三、Broadcast Channel API vs postMessage API

与 postMessage() 不同的是,你不再需要维护对 iframe 或 worker 的引用才能与其进行通信:

const popup = window.open('https://another-origin.com', ...);
popup.postMessage('Sup popup!', 'https://another-origin.com');

Broadcast Channel API 只能用于实现同源下浏览器不同窗口、Tab 页或者 iframe 下的浏览器上下文之间的简单通讯。而 postMessage API 却可用于实现不同源之间消息通信。由于保证消息来自同一来源,因此无需像以前那样使用以下方法来验证消息:

const iframe = document.querySelector('iframe');
iframe.contentWindow.onmessage = function(e) {
  if (e.origin !== 'https://expected-origin.com') {
    return;
  }
  e.source.postMessage('Ack!', e.origin);
};

四、总结

Broadcast Channel API 是一个非常简单的 API,内部包含了跨上下文通讯的接口。在支持该 API 的浏览器中,我们可以利用该 API 轻松地实现同源页面间的通信。而对于不支持该 API 的浏览器来说,我们就可以考虑使用 localStorage 和 storage 事件来解决同源页面间通信的问题。

五、参考资源

MDN - Broadcast Channel API
BroadcastChannel API: A Message Bus for the Web

以上就是JavaScript 如何实现同源通信的详细内容,更多关于JavaScript 同源通信的资料请关注我们其它相关文章!

(0)

相关推荐

  • Vue.js子组件向父组件通信的方法实例代码详解

    一.场景描述: 曾经有个电商项目,其中有个"老带新"模块,而且该模块新增的入口很多,但是新增后展示效果还不一样,当时就考虑将新增的组件单独拿出来,其实就是一个子组件向父组同步数据的过程. 当然,背景不重要了,关键是看实现的方式. 二.场景展示效果 (PS:展示效果请忽略美感) 三.如何实现 注意:Vuejs架构通过vue-cli 3.X搭建的项目,版本无所谓. 1.先看下目录体系,下图子组件放在components文件夹内,模拟子组件为itemAdd.vue,父组件视图放在views文

  • js同源策略详解

    本文较为详细的分析了js同源策略.分享给大家供大家参考.具体如下: 概念:同源策略是客户端脚本(尤其是Javascript)的重要的安全度量标准.它最早出自Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载. 这里的同源指的是:同协议,同域名和同端口. 精髓: 它的精髓很简单:它认为自任何站点装载的信赖内容是不安全的.当被浏览器半信半疑的脚本运行在沙箱时,它们应该只被允许访问来自同一站点的资源,而不是那些来自其它站点可能怀有恶意的资源. 为什么要有同源限制?

  • 在vue中使用SockJS实现webSocket通信的过程

    最近接到一个业务需求,需要做一个聊天信息的实时展示的界面,这就需要和服务器端建立webSocket连接,从而实现数据的实时获取和视图的实时刷新.在此将我的实现记录下来,希望可以给有同样需求的人一些帮助.废话少说,下面我就来讲一下我的实现过程: socksjs •客户端和服务器端api尽可能简洁,尽量靠近websocket api •支持服务端扩展和负载均衡技术 •传输层应该全面支持跨域通信 •如果受到代理服务器的限制,传输层能优雅地从一种方式回退到另一种方式 •尽可能快地建立连接 •客户端只是纯

  • JavaScript同源策略和跨域访问实例详解

    本文实例讲述了JavaScript同源策略和跨域访问.分享给大家供大家参考,具体如下: 1. 什么是同源策略 理解跨域首先必须要了解同源策略.同源策略是浏览器上为安全性考虑实施的非常重要的安全策略. 何谓同源: URL由协议.域名.端口和路径组成,如果两个URL的协议.域名和端口相同,则表示他们同源. 同源策略: 浏览器的同源策略,限制了来自不同源的"document"或脚本,对当前"document"读取或设置某些属性. (白帽子讲web安全[1]) 从一个域上加

  • Vue.js组件通信之自定义事件详解

    组件通信 从父组件向子组件通信,通过props传递数据就可以了,但Vue组件通信的场景不止有这一种,归纳起来,组件之间的通信可以用下图来表示: 自定义事件 当子组件需要向父组件传递数据时,就要用到自定义事件.子组件用**$ emit()来触发事件**,父组件用**$ on()**来监听子组件的事件. 父组件也可以直接在子组件的自定义标签上使用v-on来监听子组件触发的事件. <!DOCTYPE html> <html lang="en"> <head>

  • JS实现的ajax和同源策略(实例讲解)

    一.回顾jQuery实现的ajax 首先说一下ajax的优缺点 优点: AJAX使用Javascript技术向服务器发送异步请求: AJAX无须刷新整个页面: 因为服务器响应内容不再是整个页面,而是页面中的局部,所以AJAX性能高: jquery 实现的ajax index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <t

  • 浅谈vue websocket nodeJS 进行实时通信踩到的坑

    先说明,我并不知道出现坑的原因是什么.我只是按照别人的写法就连上了. 我的处境是这样的 我的前台是用了 vue 全家桶,启动了一个 9527 端口. 而我的后台是用 nodeJS,启动了 8081 端口. 很明显,这种情况就出现了头疼的跨域. 贴出我的代码,如下 server.js(后台) var app = express(); var server = require('http').createServer(app); var io = require('socket.io')(serve

  • JavaScript中EventBus实现对象之间通信

     一.什么是EventBus? 我个人理解:EventBus 可以实现对象之间的通信,当数据或某些特性发生改变时,能自动监听事件作出一些改变.还有更多的内容可能我还没有拓宽.怎么实现通信呢?这里通过一个例子可以理解到其中的精髓. 二.一个简单的例子 add(){ data+=1; render(data); }, minus(){ data-=1; render(data); }, multiply(){ data*=2; render(data); }, divide(){ data/=2;

  • SpringBoot实现jsonp跨域通信的方法示例

    实现jsonp跨域通信 实现基于jsonp的跨域通信方案 原理 浏览器对非同源ajax请求有限制,不允许发送跨域请求 目前跨域解决方案有两种 cros配置 jsonp请求 cros为新规范,通过一个head请求询问服务器是否允许跨域,若不允许则被拦截 jsonp则为利用浏览器不限制js脚本的同源性,通过动态创建script请求,服务器传递回一个js函数调用语法,浏览器端按照js函数正常调用回调函数 实现思路 首先确定服务器端应该如何返回数据 一次正确的jsonp请求,服务器端应该返回如下格式数据

  • 详解JS同源策略和CSRF

    概述 本文主要涉及三个关键词: 同源策略(Same-origin policy,简称 SOP) 跨站请求伪造(Cross-site request forgery,简称 CSRF) 跨域资源共享(Cross-Origin Resource Sharing,简称 CORS) 同源策略 SOP 同源 先解释何为同源:协议.域名.端口都一样,就是同源. url 同源 https://niconico.com 基准 https://niconico.com/spirit o https://sub.ni

  • 如何利用js在两个html窗口间通信

    场景:当A页面打开B页面,在B页面操作后,A页面需要同步变更数据时 A 页面 ,http://127.0.0.1:10001/A.html var domain = 'http://127.0.0.1:10001'; window.open('http://127.0.0.1:10001/B.html'); window.addEventListener('message', function (event) { if (event.origin !== domain) return; cons

随机推荐