美文网首页
2023-09-05 58fairjs插件执行过程

2023-09-05 58fairjs插件执行过程

作者: 我是小胡胡123 | 来源:发表于2023-09-04 15:33 被阅读0次
  • 页面js逻辑:逻辑lib_hotel_listview.fair.js 业务逻辑调用FairNet.requestData插件中的js方法
  • js插件:通用插件fair_net_plugin.js FairNet类requestData方法的实现
  • fair基础通用js文件: fair_core.js 定义通用js方法invokeFlutterCommonChannel
  • native js:方法jsInvokeFlutterChannelSync定义 _context[FairExecuteDartFunctionSync]

页面JS文件

页面逻辑js文件加载的逻辑:
在页面生成的js逻辑文件中,会调用js方法,这个js方法的实现将会在插件js文件中定义,这里只是对 FairNet.requestData进行调用,执行传递请求参数:

页面js逻辑文件是随着页面FairWidget的渲染而每次都会加载到内存的,通过channel调用loadMainJs方法加载native得JSContext js环境中。

并且会为每一个页面动态实时的生成一个唯一ID state2key

state2key pageName和自增id组成,每一个逻辑js文件是fairwiget创建时候加载js文件到内存的
页面加载时 #FairKey# 将会被动态替换为state2key
替换代码:

    scriptSource = scriptSource.replaceFirst(RegExp(r'#FairProps#'), fairProps);
    scriptSource = scriptSource.replaceAll(RegExp(r'#FairKey#'), pageName);
    var map = <dynamic, dynamic>{};
    map[FairMessage.PATH] = scriptSource;
    map[FairMessage.PAGE_NAME] = pageName;

页面逻辑JS文件中插件方法调用:
此段代码将会调用 FairNet.requestData方法,此方法将会在插件js文件fair_net_plugin.js中单独实现

      requestData: function requestData() {
                    const __thiz__ = this;
                    with(__thiz__) {
                        _page++;
                        FairNet.requestData({
                            method: 'GET',
                            url: 'https://wos2.58cdn.com.cn/DeFazYxWvDti/frsupload/3be6c61070d3b48c8165af5d18464c0e_hotel_list_data.json',
                            data: convertObjectLiteralToSetOrMap({
                                ['page']: _page,
                                ['pageName']: '#FairKey#',//会被替换成 state2key 即'$pageName#${GlobalState._counter++}';
                            }),
                            success: function dummy(resp) {
                                if (resp == null) {
                                    return null;
                                }
                                let data = resp.__op_idx__('data');
                                data.forEach(function dummy(item) {
                                    let dataItem = HotelModel();
                                    try {
                                        dataItem.imagePath = item.imagePath;
                                        dataItem.titleTxt = item.titleTxt;
                                        dataItem.subTxt = item.subTxt;
                                        dataItem.dist = item.dist + ' km';
                                        dataItem.reviews = item.reviews + ' reviews';
                                        dataItem.perNight = item.perNight + '';
                                    } catch (e) {
                                        dataItem.imagePath = item.__op_idx__('imagePath');
                                        dataItem.titleTxt = item.__op_idx__('titleTxt');
                                        dataItem.subTxt = item.__op_idx__('subTxt');
                                        dataItem.dist = item.__op_idx__('dist') + ' km';
                                        dataItem.reviews = item.__op_idx__('reviews') + ' reviews';
                                        dataItem.perNight = item.__op_idx__('perNight') + '';
                                    }
                                    _listData.add(dataItem);
                                });
                                setState('#FairKey#', function dummy() {});
                            }
                        });
                    }
                },

插件JS文件在根级FairApp创建时候被加载

插件JS文件:
插件的js基础js文件时在app启动时候通过
Runtime().loadCoreJs(package: package, jsPlugins: jsPlugins, baseJsSources: baseJsSources).then((value) => runApp(app));
方法加载的。这里没有#FairKey#模式字符串的替换过程
map[FairMessage.PATH] = baseJsSource + ' ; ' + pluginJsSource;
map[FairMessage.PAGE_NAME] = 'loadCoreJs';
参数解析

js插件fair_net_plugin.js 实现

 static requestData(req) {
     let respMap = {};
     let id = 'FairNet$' + (callBackId++); // ID规则 callBackId全局变量自增
     // 设置回调
     let reqFunc = {}; //回调block 存储3个回调block 
     if (req.complete) {
         reqFunc['complete'] = req.complete;
     }
     if (req.success) {
         reqFunc['success'] = req.success;
     }
     if (req.failure) {
         reqFunc['failure'] = req.failure;
     }
     FairNetCallBack[id] = reqFunc; //FairNetCallBack 全局变量将结果回调函数存储,通过ID获取callback,这样将结果回调
     // 处理参数
     let method = '';
     if (req.method) {
         method = req.method;
     }
     let url = '';
     if (req.url) {
         url = req.url;
     }
     let data = {};
     if (req.data) {
         data = mapOrSetToObject(req.data); //业务参数 
     }
     let reqMap = {
         pageName: '#FairKey#', //这个PageName其实也没啥用
         funcName: 'invokePlugin',
         'className': 'FairNet#requestData',
         args: {
             callId: id,
             method: method,
             url: url,
             data: data //这里面的 ['pageName']: '#FairKey#',就是state2key,即'$pageName#${GlobalState._counter++}';
         }
     };
//将会被转化成:
//       {
//     "pageName": "#FairKey#",
//     "funcName": "invokePlugin",
//     "className": "FairNet#requestData",
//     "args":
//     {
//         "callId": "FairNet$0",
//         "method": "GET",
//         "url": "https://wos2.58cdn.com.cn/DeFazYxWvDti/frsupload/3be6c61070d3b48c8165af5d18464c0e_hotel_list_data.json",
//         "data":
//         {
//             "page": 1,
//             "pageName": "HotelListView#0"
//         }
//     }
// }
     invokeFlutterCommonChannel(JSON.stringify(reqMap), (resultStr) =>{//调用通用的方法invokeFlutterCommonChannel这个方法在fair_core.js中定义
         let responseMap = JSON.parse(resultStr);
         let data = responseMap['data'];
         responseMap['data'] = data.data;
         let id = responseMap['callId'];
         //处理需要返回的结果值
         let callback = FairNetCallBack[id]; //从全局变量中获取回调callback,将结果回调
         if (callback == null) {
             return
         }
         let complete = callback['complete'];
         let failure = callback['failure'];
         let success = callback['success'];
         if (responseMap['statusCode'] === 200) {
             if (complete != null) {
                 complete();
             }
             if (success != null) {
                 success(convertObjectLiteralToSetOrMap(responseMap));
             }
         } else {
             if (complete != null) {
                 complete();
             }
             if (failure != null) {
                 failure(responseMap['statusMessage']);
             }
         }
     })
 }

dart 插件内置逻辑实现,fair_net_plugin.js插件的落地调用实际会走到dart,有dart实现网络请求

  static Future<dynamic> _request(dynamic map) async {


    if (map == null) {
      return;
    }
    var req;
    bool isDart;
    if (map is Map) {
      isDart = true;
      req = map;
    } else {
      isDart = false;
      req = jsonDecode(map);
    }
    var pageName = req['pageName'];
    var args = req['args'];
    if (isDart) {
      args = req;
    }

    var url = args['url'];
    var callId = args['callId'];
    var successCallback = args['success'];
    var failureCallback = args['failure'];
    var completeCallback = args['complete'];
    Map<String, dynamic> reqData = args['data'];//业务参数
    var method = args['method'];
    Response<dynamic>? response;

    if (method == null) {
      return Future.value();
    }

    switch (method) {
      case 'GET':
        response = await _get(url, queryParameters: reqData);
        break;
      case 'POST':
        response = await _post(url, queryParameters: reqData);
        break;
    }

    var statusCode = response?.statusCode;
    var data = response?.data;
    var statusMessage = response?.statusMessage;

    /// 需要判断发起方的请求是dart端还是js端
    if (isDart) {
      /// 实际处理结合自身app的业务逻辑场景
      if (200 == statusCode) {
        successCallback?.call(data);
        completeCallback?.call();
      } else {
        failureCallback?.call(statusMessage);
        completeCallback?.call();
      }
      return Future.value();
    } else {

        // let reqMap = {
        //     pageName: '#FairKey#',
        //     funcName: 'invokePlugin',
        //     'className': 'FairNet#requestData',
        //     args: {
        //         callId: id,
        //         method: method,
        //         url: url,
        //         data: data
        //     }
        // };

                //将会被转化成: map:
        //       {
        //     "pageName": "#FairKey#",
        //     "funcName": "invokePlugin",
        //     "className": "FairNet#requestData",
        //     "args":
        //     {
        //         "callId": "FairNet$0",
        //         "method": "GET",
        //         "url": "https://wos2.58cdn.com.cn/DeFazYxWvDti/frsupload/3be6c61070d3b48c8165af5d18464c0e_hotel_list_data.json",
        //         "data":
        //         {
        //             "page": 1,
        //             "pageName": "HotelListView#0"
        //         }
        //     }
        // }
      var resp = {
        'callId': callId,// 透传回调,用于调用发起方通过id寻找回调callback函数
        'pageName': pageName, //这个pageName其实就只是pageName,不是state2key
        'statusCode': response?.statusCode,
        'data': response?.data,//
        'statusMessage': response?.statusMessage,
      };


      return Future.value(jsonEncode(resp));
    }
  }

通用js fair_core.js

const invokeFlutterCommonChannel = (invokeData, callback) => {
    console.log("invokeData" + invokeData)
    jsInvokeFlutterChannel(invokeData, (resultStr) => { //调用native定义的jsInvokeFlutterChannel方法
        console.log('resultStr' + resultStr);
        if (callback) {
            callback(resultStr);
        }
    });
};

native FairExecuteDartFunctionAsync方法实现

_context[FairExecuteDartFunctionAsync] = ^(id receiver, JSValue *callback) { //native定义jsInvokeFlutterChannel方法
   FairStrongObject(strongSelf, weakSelf)
   
   NSString *data = [strongSelf convertStringWithData:receiver];
   if ([strongSelf.delegate respondsToSelector:@selector(FairExecuteDartFunctionAsync:callback:)]) {
       [strongSelf.delegate FairExecuteDartFunctionAsync:data callback:callback];
   }
};

页面逻辑js标识

state2key算法:

    state2key = GlobalState.id(widget.name);
  static String id(String? prefix) {
    return '$prefix#${GlobalState._counter++}';
  }

总结

本文主要通过从FairNet插件的使用实例Fair的ListView模版,研究插件的运行流程和工作机制。官方的用法步骤,点击查看

  • 通用js,通用的js方法调用,通过funcName,arg,pageName解析,然后进行转发。所有动态逻辑都是同一个方法名字invokeFlutterCommonChannel。
  • 插件js,页面js生成逻辑中,没有识别的js方法将需要通过插件实现,这是一个app全局级别的加载,在FairApp启动时加载到naitve JavascriptCore环境中。
  • 页面js,将页面转化为js方法,不会识别的js方法,将在js插件中查找,通过调用js中的插件方法,将参数从js逻辑中传递,调用js-native-dart-js的执行流程。另外一点就是每一个页面js都会随着页面加载动态加载,随着页面释放而释放。
  • native通用js函数名,js调用dart,dart将结果返回
  • dart实现内置逻辑使用dart实现功能

相关文章

  • MyBatis快速入门(09)全局配置--插件

    在SQL语句方法执行的过程中,MyBatis 允许你编写插件(plugin)在执行过程中的某一点进行拦截调用,执行...

  • MyBatis原理(六)——插件

    MyBatis的插件可以通过修改sql语,修改执行过程或者结果集解析,实现分页、数据的加密解密等。插件就是一个拦截...

  • pytest-几个插件及用到的参数

    pytest插件 pytest拥有丰富的第三方插件,在执行测试用例的过程中实现某些功能或是更好的帮助查看测试结果,...

  • 2023-09-05

    打的包就是这样一个个运输下来的,要干,就雷厉风行。 今天第一次从家开车到学校,不堵车30分钟,加上从家到车的磨蹭还...

  • JMeter插件的调试

    概述 本文介绍了如何在JMeter中调试插件,以方便在开发过程中了解代码的执行过程,提高开发效率。 问题描述 JM...

  • 执行过程

    想要极端的成就,必付出极端的努力,成为极端的人格。 人与人核心的差别是觉悟。 为了改变一些习惯,我对生活方式下手了...

  • Groovy (二) groovy 加固插件

    使用类似360加固 思路,下载360加固,根据命令行help配置自动执行加固打包 插件实现过程 开发方式 Buil...

  • Mybatis plugs (6)2018-08-21

     Mybatis为我们提供插件技术,在我们sql执行流程过程中创建SqlSession的四大对象进行自定义代码处理...

  • 使用pyenv和virtualenv搭建多版本Python虚拟环

    安装 pyenv-virtualenv 插件 下载pyenv-virtualenv至pyenv的插件目录 执行: ...

  • Vim 配置

    1 安装插件管理器 Vundle 2 通过~/.vimrc文件配置插件 3 安装插件 打开vim, 执行命令 P...

网友评论

      本文标题:2023-09-05 58fairjs插件执行过程

      本文链接:https://www.haomeiwen.com/subject/cbccvdtx.html