【笔记】HybridApp中使用Promise化的JS-Bridge

背景:

  • HybridApp,前端采用JS-bridge的方式调用Native的接口,如获取设备信息、拍照、人脸识别等
  • 前端封装了调用库,每次调用Native接口,需要进行两步操作(1、在window下挂载Native回调函数;2、调用InvokeNative函数,发送请求数据)

改造前:

 使用回调,在每次调用Ygritte中的方法前,必须先定义好回调函数,挂载在window[funcName]上。然后调用。

问题:

1、可能导致回调地狱:比如某个场景中,需要先判断App版本,然后调用不同的Native接口,那么就需要在回调中再次定义回调,产生嵌套;

2、无法改为同步:比如上图的场景中,在进入Home页面,在 [created] 中需要判断App版本,如果版本过低,在 [mounted] 中需要提示。使用回调的方式,理论上存在mounted执行时,  [created] 中的回调还没有执行。

改造:

  • 使用Promise对调用和回调进行改造
  • 为保证旧代码兼容,不修改原来在Ygritte中使用原型中添加接口的形式
  • 回调函数的定义封装,在回调中执行resolve
/**
 * 获得用户签名数据
 * @param {Float} lineWidth 如"1.5",传0或者null则视为使用native默认值
 * @param {String} lineColor 画笔颜色值的字符串,不带#号,如:"666666",传空字符串或null则视为使用native默认值
 * @param {String} callbackName 回调手写签名的图片,原图、背景透明、为base64编码的字符串,key为"signatureImage";如果用户取消,则回调空json
 * @version: from app version 2.4.0
 */
Ygritte.prototype.getHandWritingSignature = function(lineWidth, lineColor, callbackName){
  var args = ['knowNothing', 'getHandWritingSignature', callbackName || '', {
    lineWidth: lineWidth,
    lineColor: lineColor
  }];
  snow.invokeNative(args);
};

不修改上方原有的函数,新增下方函数封装

/**
 * 校验App返回值,避免多次回调,只执行一个resolve的问题
 * Promise的定义中一旦resolve或者reject,就不会执行后面的resolve和reject
 *
 * getPhoto: 成功获取图片数据时,会回调两次,一次参数为图片值,一次参数为undefined
 *
 * @param {string} method
 * @param {object} res
 * @returns
 */
function checkNativeReturn(method, res) {
  if (method === 'getPhoto' && (!res || '{}' === JSON.stringify(res))) return false;
  return true;
}

/**
 * Promise化的方法调用
 *
 * 白灵(Ghost)是琼恩·雪诺 的白色冰原狼 ,外观像狐狸。它的毛色净白,眼瞳红如鲜血。
 *
 * @param {object} { method, key = method, data }
 * @returns
 */
function Ghost({ method, key = method, data }) {
  return new Promise((resolve, reject) => {
    if (Ygritte[method] && typeof(Ygritte[method]) === 'function') {
      // 全局挂载App回调函数
      window[key] = (res) => {
        if (checkNativeReturn(method, res)){
          resolve(res);
          window[key] = () => {};
        } else {
          reject(res);
        }
      };
      var args = ['knowNothing', method, key || '', data];
      snow.invokeNative(args);
    } else {
      reject(new Error('不存在的Native方法,请检查method'));
    }
  });
}

改造后:

1、使用promise封装,避免在业务代码中出现在全局挂载函数的行为

2、可以使用async语法,代码表意更清晰

遗留:

1、部分Native接口调用后,会执行两次回调,原来是在业务代码中进行判断。Promise化后需要用代码磨平,因为Promise中resolve函数只会执行一次,无法保证第一次执行的是业务需要的参数。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏极客猴

Django 学习笔记之模板

本文是自己 Django 学习笔记系列的第四篇原创文章。主要接着篇文章的视图内容,讲解模板的用法。另外也说下 Django 学习笔记系列的安排。自己计划大概 1...

410
来自专栏大内老A

如何让普通变量也支持事务回滚?

有一次和人谈起关于事务的话题,谈到怎样的资源才能事务型资源。除了我们经常使用的数据库、消息队列、事务型文件系统(TxF)以及事务性注册表(TxR)等,还有那些资...

1808
来自专栏何俊林

阿里、华为、腾讯Java技术面试题精选

1695
来自专栏农夫安全

代码审计之命令执行漏洞

环境:windows + apache + mysql + php (phpstudy) 由于是在Windows下进行的测试,所以和Linux下的测试会有所不...

2806
来自专栏葡萄城控件技术团队

程序员级别鉴定书(.NET面试问答集锦)

作为一个.NET程序员,应该知道的不仅仅是拖拽一个控件到设计时窗口中。就像一个赛车手,一定要了解他的爱车 – 能做什么不能做什么。 本文参考Scott Hans...

3757
来自专栏蓝天

Oops错误

在at91rm9200下写了一个spi的驱动,加载后,运行测试程序时,蹦出这么个吓人的东西: Unable to handle kernel paging r...

1011
来自专栏Java3y

【不用框架】文件上传和下载

什么是文件上传? 文件上传就是把用户的信息保存起来。 为什么需要文件上传? 在用户注册的时候,可能需要用户提交照片。那么这张照片就应该要进行保存。 上传组件(工...

6074
来自专栏IT开发技术与工作效率

Redis 全中文总结

3114
来自专栏知无涯

ASP跨站提交参数检测

36216
来自专栏雨尘分享

2018 - iOS 面试题汇总一般面试题BAT面试题

4.2K3

扫码关注云+社区

领取腾讯云代金券