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

2023-09-04  本文已影响0人  我是小胡胡123

页面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模版,研究插件的运行流程和工作机制。官方的用法步骤,点击查看

上一篇 下一篇

猜你喜欢

热点阅读