zoukankan      html  css  js  c++  java
  • 【笔记】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函数只会执行一次,无法保证第一次执行的是业务需要的参数。

  • 相关阅读:
    滚动数组
    leetcode动态规划
    初中数学学习
    LCS最长公共子序列
    Help Jimmy
    IntelliJ IDEA 设置和查看内存使用
    无法嵌入互操作类型“ApplicationClass”。请改用适用的接口
    代码重构与单元测试——重构6:使用“多态”取代条件表达式(九)
    一个屌丝程序猿的人生(一百二十六)
    一个屌丝程序猿的人生(一百二十五)
  • 原文地址:https://www.cnblogs.com/smileSmith/p/8760964.html
Copyright © 2011-2022 走看看