【pomelo】components组件加载原理
发布于 5 年前 作者 gocpplua 1979 次浏览 来自 分享

【pomelo】components组件加载原理

文档官方中有一个简单的添加组件组件实例:给pomelo加个组件

那组件添加的原理是怎么样子的呢?请往下看。

在app.js中,第一行用于加载pomelo.js:

var pomelo = require('pomelo');

在pomelo.js的下述代码,自动加载捆绑的组件(可以看到,组件都在 pomelo\lib\components下面):

fs.readdirSync(__dirname + '/components').forEach(function (filename) {
 if (!/\.js$/.test(filename)) {
 return;
 }
 var name = path.basename(filename, '.js');
 var _load = load.bind(null, './components/', name);
 Pomelo.components.__defineGetter__(name, _load);
 Pomelo.__defineGetter__(name, _load);
});
function load(path, name) {
 if (name) {
 return require(path + name);
 }
 return require(path);
}

这里我们来看下load.bind和__defineGetter__:

bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

__defineGetter__ 方法可以将一个函数绑定在当前对象的指定属性上,当那个属性的值被读取时,你所绑定的函数就会被调用。

下面我们以 pomelo\lib\components下面第一个组件backendSession为例。 根据__defineGetter__ 可知,我们在调用Pomelo.backendSession,就是在调用_load,而_load 就是调用require(./component/backendSession)。

在Application.start 接口中,我们看到:

backendSession.js如下:

 appUtil.loadDefaultComponents(self);

上面函数如下:

module.exports.loadDefaultComponents = function(app) {
 var pomelo = require('../pomelo');
 // load system default components
 if (app.serverType === Constants.RESERVED.MASTER) {
 app.load(pomelo.master, app.get('masterConfig'));
 } else {
...
 app.load(pomelo.backendSession, app.get('backendSessionConfig')); // 这里
 app.load(pomelo.channel, app.get('channelConfig'));
 app.load(pomelo.server, app.get('serverConfig'));
 }
 app.load(pomelo.monitor, app.get('monitorConfig'));
};

接下来就解析:

app.load(pomelo.backendSession, app.get('backendSessionConfig')); 
  • pomelo.backendSession

相当于:require(./component/backendSession)

  • app.get(‘backendSessionConfig’)

代码中没有相关set,所以是undefined

接着就调用app.load:

pomelo/lib/components/backendSession.js如下:

/**
 * Load component
 *
 * @param {String} name (optional) name of the component
 * @param {Object} component component instance or factory function of the component
 * @param {[type]} opts (optional) construct parameters for the factory function
 * @return {Object} app instance for chain invoke
 * @memberOf Application
 */
Application.load = function(name, component, opts) {
 if(typeof name !== 'string') {
 opts = component;
 component = name;
 name = null;
 if(typeof component.name === 'string') {
 name = component.name;
 }
 }
 if(typeof component === 'function') {
 component = component(this, opts);
 }
 if(!name && typeof component.name === 'string') {
 name = component.name;
 }
 if(name && this.components[name]) {
 // ignore duplicat component
 logger.warn('ignore duplicate component: %j', name);
 return;
 }
 this.loaded.push(component);
 if(name) {
 // components with a name would get by name throught app.components later.
 this.components[name] = component;
 }
 return this;
};

我们分析下入参:

  • name:require(./component/backendSession)
  • comonent:undefined
  • opt:undefined

所以先进入if(typeof name !== 'string'),最后会走到:

 if(typeof component === 'function') {
 component = component(this, opts);
 }

上面代码就是调用backendSession.js函数,如下:

var BackendSessionService = require('../common/service/backendSessionService');
module.exports = function(app) {
 var service = new BackendSessionService(app);
 service.name = '__backendSession__';
 // export backend session service to the application context.
 app.set('backendSessionService', service, true); // 1. set 函数自行查看
 // for compatibility as `LocalSession` is renamed to `BackendSession` 
 app.set('localSessionService', service, true);
 return service; // 2. 返回 BackendSessionService
};

接着回到Application.load:

this.loaded.push(component);
 if(name) {
 // components with a name would get by name throught app.components later.
 this.components[name] = component; // name = '__backendSession__'
 }

接下来,我们就可以通过以下代码来访问BackendSessionService实例:

方式一、app.get('backendSessionService')
方式二、app.backendSessionService

组件如果存在:start 和 afterStart方法,通过 appUtil.optComponents调用,参数如下:

Constants.RESERVED.START
Constants.RESERVED.AFTER_START

Good Joob!!!

如有疑问或错误,或者觉得我哪里漏说明,请联系我!

回到顶部

AltStyle によって変換されたページ (->オリジナル) /