if(mod&&mod.isInitialized){
return mod.module.exports;}
好,我们抓紧回来,在上段代码中当BatchedBridge module创建时,通过这句 Object.defineProperty(global,‘__fbBatchedBridge
’,{value:BatchedBridge}); 把自己定义到JSContext的全局变量上。所以在Native代码中可以通过 JSContext[@“__fbBatchedBridge”]获取到,
从代码中也可以看到BatchedBridge 是JS类MessageQueue的实例,并且它导出的时候并没有导出构造函数MessageQueue,而是导出的实例BatchedBridge,所以它是React Native JS引擎中全局唯一的。它也是Natvie和JS互通的关键桥梁。
__fbBatchedBridge.callFunctionReturnFlushedQueue(“AppRegistr”,“runApplication”,[“MGReactNative”,{“rootTag”:1,“initialProps”:{}}])
我们继续看MessageQueue 类的callFunctionReturnFlushedQueue 函数,它最终调用到__callFunction(module, method, args)函数
__callFunction(module, method, args) {
var moduleMethods = this._callableModules[module];
if (!moduleMethods) {
moduleMethods = require(module);
}
moduleMethods[method].apply(moduleMethods, args);
}
看起来__callFunction就是最终的分发函数了,首先它从this._callableModules中找到模块对象,如果它还没有加载,就动态加载它(require),如果找到就执行最终的JS函数。
自己开发的JS模块如果暴露给Native调用
先看下AppRegistry是如何暴露给Natvie的
__d(‘AppRegistry’,function(global, require, module, exports) { ‘use strict’; var BatchedBridge=require(‘BatchedBridge’); var ReactNative=require(‘ReactNative’); var AppRegistry={ runApplication:function(appKey,appParameters){ runnables[appKey].run(appParameters); }, } BatchedBridge.registerCallableModule( ‘AppRegistry’, AppRegistry); module.exports=AppRegistry; });
有前面的讲解,现在看这个应该不态费劲了,可以看到AppRegistry模块工厂函数中,执行了 BatchedBridge.registerCallableModule(‘AppRegistry’,AppRegistry);,把自己注册到BatchedBridge的CallableModule中,所以在上一节中,__callFunction才能在_callableModules
找到AppRegistry实例,才能调用其runApplication函数。自己写的模块代码可以用React Native这种方式暴露给Natvie调用,和直接暴露的区别是,符合React Natvie的模块化原则,另外一个直观的好处是你的模块可以是懒加载的,并且不会污染全局空间。
目前终于把从N-JS的整个路径跑通了,我们梳理下整个流程看看。
[RCTBatchedBridge enqueueJSCall:@“AppRegistry.runApplication” args:[“MGReactNative”,{“rootTag”:1,“initialProps”:{}}]];
RCTJavaScriptContext callFunctionOnModule:@“AppRegistr”
method:@"runApplication"
arguments:["MGReactNative",{"rootTag":1,"initialProps":{}}]
callback:(RCTJavaScriptCallback)onComplete
//main.js
__fbBatchedBridge.callFunctionReturnFlushedQueue(“AppRegistr”,“runApplication”,[“MGReactNative”,{“rootTag”:1,“initialProps”:{}}])
//main.js
BatchedBridge.__callFunction(“AppRegistr”,“runApplication”,[“MGReactNative”,{“rootTag”:1,“initialProps”:{}}])
//main.js
var moduleMethods = BatchedBridge._callableModules[module];
if (!moduleMethods) {
moduleMethods = require(module);