页面和应用之间的交互(2)

前言

上个月探讨了 一次页面与应用之间的通信,主要利用浏览器扩展来进行通讯。这次来详细研究下具体实现。

探讨前的另一种思考

上个月其实还思考了一种结合性拉起应用的方式。由于通过URI拉起应用,js端无法接受到任何反馈,意味着无法判断应用是否有被拉起。于是思考了另一种方式:

  1. 页面URI 拉应用,同时询问后台应用是否被拉起?
  2. 应用被拉起后则会想后台发送消息。消息包括被拉起信息和ws端口。
  3. 后台接收到应用的消息后反馈给页面。
  4. 页面收到后台消息后与应用通信。一段时间没收到则告诉用户URI地址不对或者应用没有安装

这是一种一套代码多端可行性的方案,但是由于期间通信过程较为繁琐(唯一Id值,当前系统环境等等),可能出现不可预知的bug,暂时放弃了。以后有时间再详细研究一番。

IE

ie 之所以放到第一位,是因为它太特殊了。没有扩展,ie10往下不支持websocket。拉起应用除了不可靠的URI就只剩下只此一家的 new ActiveXObject(str),其中str代表注册列表中拉起应用的脚本和配置。粗看和扩展拉起应用很相似,但是却要复杂很多。IE方面等研究出成果了再添加。

判断是否安装了扩展

现在主流浏览器基本都支持扩展了。所以我们主要还是以通过扩展拉起应用为主。先把准备代码写好(判断系统,浏览器)。然后再判断是否安装了扩展。js是不能去改变,访问浏览器是否安装了扩展的,只能由扩展来告诉页面。我们在扩展的配置文件里头配置好content.js文件在页面渲染完成后加载,然后 content.js 里头添加如下代码:

1
2
3
var miniDom = document.createElement('div');
miniDom.setAttribute('id', 'test')
document.body.appendChild(miniDom); // 判断插件安装

只要找到id为设定好的特殊值就说明安装了扩展

不通过扩展通信

扩展是可以和页面通信的(相互监听对方的事件,并获取值),但是不推荐。一来各个浏览器之间写的通信代码不相同,增大了项目体积和难度,二来出了问题不好排查,层级太深。通信过程是一个 页面–>content–>background–>native的过程,中间任何一个环节有问题都需要花大量时间排查。而扩展的主要作用就是拉起应用并告诉页面即可,只需要触发事件,不需要传递数据。

通过websocket通信

IE当然只能通过轮询刷接口来通信了。因为在系统中,拉起一个应用就是起了一个服务器,它有自己的端口号。现在就是需要确定应用的端口号。当然可以通过扩展来传递,这很简单直接。也可以通过ws询问一个区间的端口号来获取。ws 连接某一个端口,如果走了onerror回调就继续下一个端口,如果onopen了就发送一个密令过去,onmessage回来与约定一致即正确端口。这个方法繁琐点,但是bug会少一些。建议使用递归。

困难

将IE,chrome,firefox,edge,safari拉起应用的代码处理整合到一起,只需要单独将IE拎出来考虑就行了。但是真正困难的还是edge和safari的扩展部分。需要C#和swift两门新语言才能完全弄懂。这也就不会出现在前端er的考虑范围了。

总结

IE。new 一个activeObject对象,通过和这个对象的对话来确认拉起应用,并通过轮询http请求来通信。

非IE。首先确认是否安装扩展,扩展拉起应用,通过websocket 进行实时通信。

此案例参考 IBM的aspera的通信方式。


作者简介: 张栓,人和未来大数据前端工程师,专注于 html/css/js 的学习与开发。