Pomelo之application的start
2015-10-16 15:00
429 查看
这篇文章要分析如下部分的代码:
[javascript]
view plaincopyprint?
// app configure
app.configure('production|development', function() {
// route configures
app.route('chat', routeUtil.chat); //chat是server类型,第二个是route函数
// filter configures
app.filter(pomelo.timeout()); //这里会同时在before和after加入这个filter
});
// start app
app.start(); //开启application
其中最主要的其实还是分析application的start过程,先来看看configure要干一些什么东西吧:
[javascript]
view plaincopyprint?
Application.configure = function (env, type, fn) {
var args = [].slice.call(arguments); //将传进来的参数变成一个数组
fn = args.pop(); //获取回调函数
env = 'all';
type = 'all';
if(args.length > 0) {
env = args[0]; //获取当前额环境配置,例如development,production等
}
if(args.length > 1) {
type = args[1]; //类型,conector,gate啥的
}
if (env === 'all' || contains(this.settings.env, env)) { //如果没有配置env或者env包含在了配置中,
if (type === 'all' || contains(this.settings.serverType, type)) {
fn.call(this); //调用回调函数
}
}
return this;
};
代码应该还算是很简单的吧,先将传进来的参数转化为一个数组,然后获取最后的回调函数,接着判断当前环境配置是否符合,然后再调用回调函数,进行一些设置,例如我们来看看route干了些什么:
[javascript]
view plaincopyprint?
//设置相应server的route函数
pplication.route = function(serverType, routeFunc) {
var routes = this.get('__routes__');
if(!routes) {
routes = {};
this.set('__routes__', routes);
}
routes[serverType] = routeFunc; //保存route函数
return this;
;
然后filter用来设置filter函数,这里比较有意思的是filter分为两个维度,分别是before和after,这里会同时在这两个维度中都设置这个传进去的filter函数。。。
好了,接下来进入主题,看start函数吧:
[javascript]
view plaincopyprint?
Application.start = function(cb) {
if(this.state > STATE_INITED) { //正常情况应该是等于这个
utils.invokeCallback(cb, new Error('application has already start.'));
return;
}
appUtil.loadDefaultComponents(this); //用来加载默认的组件
var self = this;
//调用这些组件的start,开启这些组件
appUtil.optComponents(this.loaded, 'start', function(err) {
self.state = STATE_START;
if(err) {
utils.invokeCallback(cb, err);
} else {
logger.info('%j enter after start...', self.getServerId());
self.afterStart(cb);
}
});
};
[javascript]
view plaincopyprint?
//为application加载默认的组件
odule.exports.loadDefaultComponents = function(app) {
var pomelo = require('../pomelo');
// load system default components
if (app.serverType === 'master') {
app.load(pomelo.master, app.get('masterConfig')); //get得到的为null
//这里pomelo.master在pomelo里面定义了,会载入components里面的master文件,这里的master其实是包装器,真正的master会在里面加载
} else {
app.load(pomelo.proxy, app.get('proxyConfig'));
if(app.getCurServer().port) {
app.load(pomelo.remote, app.get('remoteConfig'));
}
if(app.isFrontend()) {
app.load(pomelo.connection, app.get('connectionConfig'));
app.load(pomelo.connector, app.get('connectorConfig'));
app.load(pomelo.session, app.get('sessionConfig'));
app.load(pomelo.protobuf, app.get('protobufConfig'));
app.load(pomelo.scheduler, app.get('schedulerConfig'));
}
app.load(pomelo.localSession, app.get('localSessionConfig'));
app.load(pomelo.channel, app.get('channelConfig'));
app.load(pomelo.server, app.get('serverConfig'));
if(app.get('globalChannelConfig')) {
app.load(pomelo.globalChannel, app.get('globalChannelConfig'));
}
}
app.load(pomelo.monitor, app.get('monitorConfig'));
;
在深入load之前,需要知道pomelo.master究竟是个什么东西。。。
回顾以前的一段代码:
[javascript]
view plaincopyprint?
//用于在components文件夹中读取组件,然后保存到components对象里面去
s.readdirSync(__dirname + '/components').forEach(function (filename) {
if (!/\.js$/.test(filename)) {
return;
}
var name = path.basename(filename, '.js');
function load() {
return require('./components/' + name);
}
Pomelo.components.__defineGetter__(name, load);//例如执行Pomelo.components.aa,其实会得到require("./components/aa");的值
Pomelo.__defineGetter__(name, load);
);
[java]
view plaincopyprint?
function load() {
return require('./components/master');
}
[javascript]
view plaincopyprint?
/**
* Component for master.
*/
var Master = require('../master/master');
/**
* Component factory function
*
* @param {Object} app current application context
* @return {Object} component instances
*/
//相当于require之后得到的就是这个函数
module.exports = function (app) { return new Component(app); };
/**
* Master component class
*
* @param {Object} app current application context
*/
var Component = function (app) {
this.master = new Master(app); //创建爱你master
};
var pro = Component.prototype;
/**
* Component lifecycle function
*
* @param {Function} cb
* @return {Void}
*/
pro.start = function (cb) { this.master.start(cb); };
/**
* Component lifecycle function
*
* @param {Boolean} force whether stop the component immediately
* @param {Function} cb
* @return {Void}
*/
pro.stop = function (force, cb) {
this.master.stop(cb);
};
从这里我们可以看到,访问pomelo.master实际上得到的是如下这个函数:
[javascript]
view plaincopyprint?
function (app) { return new Component(app); };
好了,搞清楚了pomelo.master是个什么东西,接下来我们就可以深入load函数了:
[javascript]
view plaincopyprint?
//该函数用于加载组件,
pplication.load = function(name, component, opts) {
if(typeof name !== 'string') {
opts = component; //工厂方法,例如start,stop等
component = name; //加载得到的component
name = null;
if(typeof component.name === 'string') {
name = component.name;
}
}
if(typeof component === 'function') { //如果是方法,那么就是component的构造方法,其实一般情况下就是这个样子的
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); //将家在得到的component放入到数组
if(name) {
// components with a name would get by name throught app.components later.
this.components[name] = component;
}
return this;
;
好了,master组件load进来了,那么就应该启动了,也即是执行如下的代码:
[javascript]
view plaincopyprint?
//调用这些组件的start,开启这些组件
appUtil.optComponents(this.loaded, 'start', function(err) {
self.state = STATE_START;
if(err) {
utils.invokeCallback(cb, err);
} else {
logger.info('%j enter after start...', self.getServerId());
self.afterStart(cb);
}
});
[javascript]
view plaincopyprint?
module.exports.optComponents = function(comps, method, cb) {
var i = 0;
//遍历所有的组件,调用他们相应的方法
async.forEachSeries(comps, function(comp, done) {
i++;
if(typeof comp[method] === 'function') {
comp[method](done);
} else {
done();
}
}, function(err) {
if(err) {
logger.error('fail to operate component, method:%s, err:' + err.stack, method);
}
cb(err);
});
[javascript]
view plaincopyprint?
pro.start = function (cb) { this.master.start(cb); };
好了,到这里master组件的载入和start也就差不多了,那么下一篇就可以看看master的start究竟是干了些什么事情了。。。
这篇文章要分析如下部分的代码:
[javascript]
view plaincopyprint?
// app configure
app.configure('production|development', function() {
// route configures
app.route('chat', routeUtil.chat); //chat是server类型,第二个是route函数
// filter configures
app.filter(pomelo.timeout()); //这里会同时在before和after加入这个filter
});
// start app
app.start(); //开启application
// app configure app.configure('production|development', function() { // route configures app.route('chat', routeUtil.chat); //chat是server类型,第二个是route函数 // filter configures app.filter(pomelo.timeout()); //这里会同时在before和after加入这个filter }); // start app app.start(); //开启application
其中最主要的其实还是分析application的start过程,先来看看configure要干一些什么东西吧:
[javascript]
view plaincopyprint?
Application.configure = function (env, type, fn) {
var args = [].slice.call(arguments); //将传进来的参数变成一个数组
fn = args.pop(); //获取回调函数
env = 'all';
type = 'all';
if(args.length > 0) {
env = args[0]; //获取当前额环境配置,例如development,production等
}
if(args.length > 1) {
type = args[1]; //类型,conector,gate啥的
}
if (env === 'all' || contains(this.settings.env, env)) { //如果没有配置env或者env包含在了配置中,
if (type === 'all' || contains(this.settings.serverType, type)) {
fn.call(this); //调用回调函数
}
}
return this;
};
Application.configure = function (env, type, fn) { var args = [].slice.call(arguments); //将传进来的参数变成一个数组 fn = args.pop(); //获取回调函数 env = 'all'; type = 'all'; if(args.length > 0) { env = args[0]; //获取当前额环境配置,例如development,production等 } if(args.length > 1) { type = args[1]; //类型,conector,gate啥的 } if (env === 'all' || contains(this.settings.env, env)) { //如果没有配置env或者env包含在了配置中, if (type === 'all' || contains(this.settings.serverType, type)) { fn.call(this); //调用回调函数 } } return this; };
代码应该还算是很简单的吧,先将传进来的参数转化为一个数组,然后获取最后的回调函数,接着判断当前环境配置是否符合,然后再调用回调函数,进行一些设置,例如我们来看看route干了些什么:
[javascript]
view plaincopyprint?
//设置相应server的route函数
pplication.route = function(serverType, routeFunc) {
var routes = this.get('__routes__');
if(!routes) {
routes = {};
this.set('__routes__', routes);
}
routes[serverType] = routeFunc; //保存route函数
return this;
;
//设置相应server的route函数 Application.route = function(serverType, routeFunc) { var routes = this.get('__routes__'); if(!routes) { routes = {}; this.set('__routes__', routes); } routes[serverType] = routeFunc; //保存route函数 return this; };这个应该是一看就能看明白这个用来干嘛了吧,第一个参数是设置route的server类型,说白了就是将这个用键值对保存起来,routefunc一般是用户自定义的route函数吧。。以后的分析肯定会涉及到。。。
然后filter用来设置filter函数,这里比较有意思的是filter分为两个维度,分别是before和after,这里会同时在这两个维度中都设置这个传进去的filter函数。。。
好了,接下来进入主题,看start函数吧:
[javascript]
view plaincopyprint?
Application.start = function(cb) {
if(this.state > STATE_INITED) { //正常情况应该是等于这个
utils.invokeCallback(cb, new Error('application has already start.'));
return;
}
appUtil.loadDefaultComponents(this); //用来加载默认的组件
var self = this;
//调用这些组件的start,开启这些组件
appUtil.optComponents(this.loaded, 'start', function(err) {
self.state = STATE_START;
if(err) {
utils.invokeCallback(cb, err);
} else {
logger.info('%j enter after start...', self.getServerId());
self.afterStart(cb);
}
});
};
Application.start = function(cb) { if(this.state > STATE_INITED) { //正常情况应该是等于这个 utils.invokeCallback(cb, new Error('application has already start.')); return; } appUtil.loadDefaultComponents(this); //用来加载默认的组件 var self = this; //调用这些组件的start,开启这些组件 appUtil.optComponents(this.loaded, 'start', function(err) { self.state = STATE_START; if(err) { utils.invokeCallback(cb, err); } else { logger.info('%j enter after start...', self.getServerId()); self.afterStart(cb); } }); };其实这个函数的定义相对还是比较容易搞明白,首先判断当前的状态,如果都已经开启了,那么就报错,正常情况下应该是加载那些默认的组件,然后在开启这些组件。。。来看看loadDefaultComponents方法:
[javascript]
view plaincopyprint?
//为application加载默认的组件
odule.exports.loadDefaultComponents = function(app) {
var pomelo = require('../pomelo');
// load system default components
if (app.serverType === 'master') {
app.load(pomelo.master, app.get('masterConfig')); //get得到的为null
//这里pomelo.master在pomelo里面定义了,会载入components里面的master文件,这里的master其实是包装器,真正的master会在里面加载
} else {
app.load(pomelo.proxy, app.get('proxyConfig'));
if(app.getCurServer().port) {
app.load(pomelo.remote, app.get('remoteConfig'));
}
if(app.isFrontend()) {
app.load(pomelo.connection, app.get('connectionConfig'));
app.load(pomelo.connector, app.get('connectorConfig'));
app.load(pomelo.session, app.get('sessionConfig'));
app.load(pomelo.protobuf, app.get('protobufConfig'));
app.load(pomelo.scheduler, app.get('schedulerConfig'));
}
app.load(pomelo.localSession, app.get('localSessionConfig'));
app.load(pomelo.channel, app.get('channelConfig'));
app.load(pomelo.server, app.get('serverConfig'));
if(app.get('globalChannelConfig')) {
app.load(pomelo.globalChannel, app.get('globalChannelConfig'));
}
}
app.load(pomelo.monitor, app.get('monitorConfig'));
;
//为application加载默认的组件 module.exports.loadDefaultComponents = function(app) { var pomelo = require('../pomelo'); // load system default components if (app.serverType === 'master') { app.load(pomelo.master, app.get('masterConfig')); //get得到的为null //这里pomelo.master在pomelo里面定义了,会载入components里面的master文件,这里的master其实是包装器,真正的master会在里面加载 } else { app.load(pomelo.proxy, app.get('proxyConfig')); if(app.getCurServer().port) { app.load(pomelo.remote, app.get('remoteConfig')); } if(app.isFrontend()) { app.load(pomelo.connection, app.get('connectionConfig')); app.load(pomelo.connector, app.get('connectorConfig')); app.load(pomelo.session, app.get('sessionConfig')); app.load(pomelo.protobuf, app.get('protobufConfig')); app.load(pomelo.scheduler, app.get('schedulerConfig')); } app.load(pomelo.localSession, app.get('localSessionConfig')); app.load(pomelo.channel, app.get('channelConfig')); app.load(pomelo.server, app.get('serverConfig')); if(app.get('globalChannelConfig')) { app.load(pomelo.globalChannel, app.get('globalChannelConfig')); } } app.load(pomelo.monitor, app.get('monitorConfig')); };我们还是先来看master类型吧,因为我们现在整个代码的流程还是在master类型中,还没有涉及到server类型,这里直接调用load方法将master载入进来。。。至于后面得到的配置,其实是null。
在深入load之前,需要知道pomelo.master究竟是个什么东西。。。
回顾以前的一段代码:
[javascript]
view plaincopyprint?
//用于在components文件夹中读取组件,然后保存到components对象里面去
s.readdirSync(__dirname + '/components').forEach(function (filename) {
if (!/\.js$/.test(filename)) {
return;
}
var name = path.basename(filename, '.js');
function load() {
return require('./components/' + name);
}
Pomelo.components.__defineGetter__(name, load);//例如执行Pomelo.components.aa,其实会得到require("./components/aa");的值
Pomelo.__defineGetter__(name, load);
);
//用于在components文件夹中读取组件,然后保存到components对象里面去 fs.readdirSync(__dirname + '/components').forEach(function (filename) { if (!/\.js$/.test(filename)) { return; } var name = path.basename(filename, '.js'); function load() { return require('./components/' + name); } Pomelo.components.__defineGetter__(name, load);//例如执行Pomelo.components.aa,其实会得到require("./components/aa");的值 Pomelo.__defineGetter__(name, load); });在componets里面有了master.js文件,那么我们就知道如果访问pomelo.master,那么实际得到的是
[java]
view plaincopyprint?
function load() {
return require('./components/master');
}
function load() { return require('./components/master'); }这个函数的返回值,那么我们再来看看这个东西的定义吧:
[javascript]
view plaincopyprint?
/**
* Component for master.
*/
var Master = require('../master/master');
/**
* Component factory function
*
* @param {Object} app current application context
* @return {Object} component instances
*/
//相当于require之后得到的就是这个函数
module.exports = function (app) { return new Component(app); };
/**
* Master component class
*
* @param {Object} app current application context
*/
var Component = function (app) {
this.master = new Master(app); //创建爱你master
};
var pro = Component.prototype;
/**
* Component lifecycle function
*
* @param {Function} cb
* @return {Void}
*/
pro.start = function (cb) { this.master.start(cb); };
/**
* Component lifecycle function
*
* @param {Boolean} force whether stop the component immediately
* @param {Function} cb
* @return {Void}
*/
pro.stop = function (force, cb) {
this.master.stop(cb);
};
/** * Component for master. */ var Master = require('../master/master'); /** * Component factory function * * @param {Object} app current application context * @return {Object} component instances */ //相当于require之后得到的就是这个函数 module.exports = function (app) { return new Component(app); }; /** * Master component class * * @param {Object} app current application context */ var Component = function (app) { this.master = new Master(app); //创建爱你master }; var pro = Component.prototype; /** * Component lifecycle function * * @param {Function} cb * @return {Void} */ pro.start = function (cb) { this.master.start(cb); }; /** * Component lifecycle function * * @param {Boolean} force whether stop the component immediately * @param {Function} cb * @return {Void} */ pro.stop = function (force, cb) { this.master.stop(cb); };(呵呵,看起来不就是一个包装器么。。。用于对真正的master进行一个代理而已。。)
从这里我们可以看到,访问pomelo.master实际上得到的是如下这个函数:
[javascript]
view plaincopyprint?
function (app) { return new Component(app); };
function (app) { return new Component(app); };
好了,搞清楚了pomelo.master是个什么东西,接下来我们就可以深入load函数了:
[javascript]
view plaincopyprint?
//该函数用于加载组件,
pplication.load = function(name, component, opts) {
if(typeof name !== 'string') {
opts = component; //工厂方法,例如start,stop等
component = name; //加载得到的component
name = null;
if(typeof component.name === 'string') {
name = component.name;
}
}
if(typeof component === 'function') { //如果是方法,那么就是component的构造方法,其实一般情况下就是这个样子的
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); //将家在得到的component放入到数组
if(name) {
// components with a name would get by name throught app.components later.
this.components[name] = component;
}
return this;
;
//该函数用于加载组件, Application.load = function(name, component, opts) { if(typeof name !== 'string') { opts = component; //工厂方法,例如start,stop等 component = name; //加载得到的component name = null; if(typeof component.name === 'string') { name = component.name; } } if(typeof component === 'function') { //如果是方法,那么就是component的构造方法,其实一般情况下就是这个样子的 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); //将家在得到的component放入到数组 if(name) { // components with a name would get by name throught app.components later. this.components[name] = component; } return this; };这里我们可以知道最开始传进的name是上面提到的那个函数,其余的都是null,那么这个函数的整个执行流程也就很很明白了,调用刚刚那个函数,创建一个创建一个component,其实这个component其实是对master的一个包装而已(start,stop方法),然后再将这个component放到loaded数组当中去。。这就是组件的load过程。。。。(当然这里只是master的load过程)
好了,master组件load进来了,那么就应该启动了,也即是执行如下的代码:
[javascript]
view plaincopyprint?
//调用这些组件的start,开启这些组件
appUtil.optComponents(this.loaded, 'start', function(err) {
self.state = STATE_START;
if(err) {
utils.invokeCallback(cb, err);
} else {
logger.info('%j enter after start...', self.getServerId());
self.afterStart(cb);
}
});
//调用这些组件的start,开启这些组件 appUtil.optComponents(this.loaded, 'start', function(err) { self.state = STATE_START; if(err) { utils.invokeCallback(cb, err); } else { logger.info('%j enter after start...', self.getServerId()); self.afterStart(cb); } });好吧,我们来看这个函数的定义:
[javascript]
view plaincopyprint?
module.exports.optComponents = function(comps, method, cb) {
var i = 0;
//遍历所有的组件,调用他们相应的方法
async.forEachSeries(comps, function(comp, done) {
i++;
if(typeof comp[method] === 'function') {
comp[method](done);
} else {
done();
}
}, function(err) {
if(err) {
logger.error('fail to operate component, method:%s, err:' + err.stack, method);
}
cb(err);
});
module.exports.optComponents = function(comps, method, cb) { var i = 0; //遍历所有的组件,调用他们相应的方法 async.forEachSeries(comps, function(comp, done) { i++; if(typeof comp[method] === 'function') { comp[method](done); } else { done(); } }, function(err) { if(err) { logger.error('fail to operate component, method:%s, err:' + err.stack, method); } cb(err); });比较的简单,对于这里我们载入的master组件,说白了就是调用它的start函数,
[javascript]
view plaincopyprint?
pro.start = function (cb) { this.master.start(cb); };
pro.start = function (cb) { this.master.start(cb); };只不过是一个包装而已,用于调用真正的master的start函数。。。
好了,到这里master组件的载入和start也就差不多了,那么下一篇就可以看看master的start究竟是干了些什么事情了。。。
相关文章推荐
- Activity的生命周期理解
- Android Bitmap和Canvas
- [ios]AVCaptureSession 在横向模式在 iPad 上的问题
- Android布局大全
- Andrid利用FLAG_ACTIVITY_CLEAR_TOP实现退出APP
- Swift2.1 语法指南——高级操作符
- android数据库ORM框架GreenDao
- 使用ngrok 将本地项目发布到公网,用于微信公众平台通过80端口访问本机
- 使用YourAPP开发温度宝应用
- myeclipse中Web App Libraries无法自动识别lib下的jar包
- IOS 本地通知推送消息
- android-Ultra-Pull-To-Refresh 源码解析
- Android内存优化之一:MAT使用入门
- Unity3D 游戏在 iOS 上因为 trampolines 闪退的原因与解决办法
- Android系统层次结构是怎样的?各个层之间关系是什么?
- ANDROID开发之SQLite详解
- pomelo之application的创建于初始化
- Object-C 零碎知识点笔记
- Android学习日志之一:Intent知识点及其应用
- Android XListView 如何实现 自动下拉刷新