You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
functionpromiseTimeOut(time){returnnewPromise((resolve,reject)=>{setTimeout(resolve,time);});}promiseTimeOut(1000).then(()=>{console.log('time is ready');})
背景
关于JSBridge的一些基础知识,在网络上有很多文章可以参考:
最近公司在做一个项目,通过把我们自己的Webview植入第三方APP,然后我们的业务全部通过H5实现。至于为什么不直接用第三方APP WebView,主要是身处金融行业,需要做一些风控相关功能。
由于是Hybrid APP的性质,所以web与Native的通信是无法避免的;而为什么我要封装JSBridge,主要在于下面两点:
由于本次项目只涉及到Andriod,所以没有关于ios的处理,但我自认为他们只是协议的不同,Web的处理可以相同。
原理浅谈
看上图的通信实现(图片来源于文章开头的文章),简单说一下通信过程;
看上面的通信过程,貌似很简单。但这里面存在一些协议的问题:
回调函数注册到全局
;所以下面就来解决这些问题
一步一步的具体实现
接口协议封装
什么意思喃?看下面的图:
由于APP端协议及分包问题, 存在多个Bridge, 比如MBDevice、MBControl、MBFinance,上面列出来的只是一小部分,对于web来说记忆这些接口是一件很费事的事;还有就是以前我调APP的JSBridge, 总有下面这样的代码:
至于上面,所以加了一层封装,实现的核心就是Proxy和Map,具体实现看下面的伪代码:
基于上面的封装,调用时,代码就是下面这样
序列化与回调注册
上面已经列了为什么需要回调函数全局注册和序列化,这里主要说一下实现原理,总得来说分两步;
回调函数剥离和参数序列化
其实很好实现,直接展开运算符搞定:
函数全局注册
看了很多文章的一些实现,思路基本一致,比如下面这样
这是一种很容易想到的问题,但却存在一些问题,比如:
基于以上考虑,我换了一个方案,采用回调队列,因为APP端说过,回调是按顺序的,不会插队;
基于以上的实现,就可以保证发起多个Native请求,并保证有序回调;如果成功,成功回调被响应时,响应的失败回调也会被弹出,因为回调函数式存在数组中的,所以执行完后,引用就不会再存在。
完整实现
看了上面的代码实现,但核心好像还没有提及,那就是调用参数的拦截。前面我们用Proxy的get优雅的实现了SDK方法的拦截,这里会接着采用Proxy的apply方法来拦截方法调用的传参,直接看代码吧:
Promise 封装
前面吹过的牛逼还有两个没实现,比如:
首先来复习一下,怎么封装一个支持Promise的setTimeout函数:
如果对上面这个封装不陌生,那基于回调函数的Promise化就变得简单了
完整实现:
而调用时,基本上,就可以这样玩了:
解惑
开始函数的调用是采用func.call来实现的,当时我本地mock过,没有问题。但在webview中就弹出了下面这样一个错误:
经过各种goggle,百度,查到的都是一条关于Andriod的注入漏洞。而至于我这里通过JS的方式把bridge指向的函数地址,赋值给一个变量名,然后再通过变量名来调用就会报上面这个错误,我个人的猜测有两个:一是协议这样规定的;二是this指向问题。
如果有知道为什么的大佬,还请不吝赐教,谢谢。
通过这一次的封装,自己对Proxy的应用更加熟练了,将所学的知识运用到工作中,不得不说是一件非常愉快的事情。这也是自己第二篇关于ES6深入理解的文章;
第一篇: 重新认识ES6中的Set
原价见:issue , 如有不严谨之处,还请及时指正。
The text was updated successfully, but these errors were encountered: