pomelo 소스 분석(3) - 설정 및 읽기 및 app.load
다음을 수행합니다.https://github.com/NetEase/chatofpomelo/tree/master/game-server서버는 예를 들어 읽기 설정이 어떻게 완성되었는지 설명하고chatofpomelo는pomelo를 채팅 서버로 하는 예이다.그것의 입구점은 앱이다.js.코드 내용은 다음과 같습니다.
var pomelo = require('pomelo');
var routeUtil = require('./app/util/routeUtil');
/**
* Init app for client.
*/
var app = pomelo.createApp();
//
app.set('name', 'chatofpomelo');
// app configure
app.configure('production|development', function() {
// route configures
app.route('chat', routeUtil.chat);
//
app.set('connectorConfig', {
connector: pomelo.connectors.sioconnector,
// 'websocket', 'polling-xhr', 'polling-jsonp', 'polling'
transports: ['websocket', 'polling'],
heartbeats: true,
closeTimeout: 60 * 1000,
heartbeatTimeout: 60 * 1000,
heartbeatInterval: 25 * 1000
});
// filter configures
app.filter(pomelo.timeout());
});
// start app
app.start();
//
process.on('uncaughtException', function(err) {
console.error(' Caught exception: ' + err.stack);
});
코드에서 볼 때 모두 앱을 통해 보입니다.set 추가 설정 - 이것은 Pomelo가 비교적 다른 부분입니다. 흔히 볼 수 있는 설정은 여러 개의 파일로 나뉘어진include 방식으로 한 파일에 집중됩니다.아니면 서류가 하나밖에 없거나.그러나 Pomelo의 설정은 흩어져서 이것저것 어울릴 수 있다.app.set 이 함수의 정의는 응용 프로그램에 있습니다.js의 내용은 다음과 같다.
/**
* Assign `setting` to `val`, or return `setting`'s value.
*
* Example:
*
* app.set('key1', 'value1');
* app.get('key1'); // 'value1'
* app.key1; // undefined
*
* app.set('key2', 'value2', true);
* app.get('key2'); // 'value2'
* app.key2; // 'value2'
*
* @param {String} setting the setting of application
* @param {String} val the setting's value
* @param {Boolean} attach whether attach the settings to application
* @return {Server|Mixed} for chaining, or the setting value
* @memberOf Application
*/
Application.set = function (setting, val, attach) {
if (arguments.length === 1) {
return this.settings[setting];
}
this.settings[setting] = val;
if(attach) {
this[setting] = val;
}
return this;
};
이 함수의 주석은 매우 상세하게 썼다. 내가 앞에서 방금 분석한 c 코드에 비해 그 코드는 기본적으로 주석이 없다.코드에서 알 수 있듯이 실제로는settings에 설정을 추가했다.settings의 초기화는 settings={}입니다. 즉, 처음에는 빈 대상입니다.
여기에 설정된 설정은 분석이 끝났고pomelo는 이렇게 간단하고 직접적이다.설정된 키는 connectorConfig이고value는 js 대상입니다.다음은 그것이 어디에서 읽혔는지 살펴보자.그것은 틀림없이 Application에 있을 것이다.start에서 읽은 거예요.
/**
* Start application. It would load the default components and start all the loaded components.
*
* @param {Function} cb callback function
* @memberOf Application
*/
Application.start = function(cb) {
this.startTime = Date.now();
if(this.state > STATE_INITED) {
utils.invokeCallback(cb, new Error('application has already start.'));
return;
}
var self = this;
appUtil.startByType(self, function() { // startByType
appUtil.loadDefaultComponents(self); // startByType
var startUp = function() {
appUtil.optComponents(self.loaded, Constants.RESERVED.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);
}
});
};
var beforeFun = self.lifecycleCbs[Constants.LIFECYCLE.BEFORE_STARTUP];
if(!!beforeFun) {
beforeFun.call(null, self, startUp);
} else {
startUp();
}
});
};
appUtil.startByType 이 편은 언급하지 않고 바로 리셋을 보았습니다. 리셋의 첫 번째 줄은 바로 appUtil입니다.loadDefaultComponents, 이 함수는 설정을 읽습니다.그러나 이 함수는 매우 좋지 않은 행동을 한다. 바로 문자의 상수는 기본적으로 하드코딩이다. 즉, 모두가 흔히 말하는 코드에 죽도록 쓴다.코드를 보지 않으면 아무도 이 설정을 모르면 반드시 이 이름을 불러야 한다.
/**
* Load default components for application.
*/
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.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'));
// compatible for schedulerConfig
if(app.get('schedulerConfig')) {
app.load(pomelo.pushScheduler, app.get('schedulerConfig'));
} else {
app.load(pomelo.pushScheduler, app.get('pushSchedulerConfig'));
}
}
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입니다.connector, 이 물건은 실제로는
__defineGetter__
로 함수의 봉인을 한 번 했는데, 실제로는 함수이다.__defineGetter__
표준 안에 있는 게 아니에요./**
* 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') { //name
opts = component; //
component = name; //
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);
if(name) {
// components with a name would get by name throught app.components later.
this.components[name] = component;
}
return this;
};
그래서load라는 함수에서name가 들어오는 것은 실제 함수이고 이 함수를 호출하여opts를 매개 변수로 들어간다.이렇게 하면 모듈의 적재를 실현하였다.
팝업으로.connector는 예를 들어 모듈을 불러오는 과정을 설명합니다. 위에서pomelo를 설명했습니다.connector는 실제로 함수입니다. 이것은 어떻게 실현됩니까?우선 Pomelo로 가세요.js에서 검색하면 찾을 수 없을 거야.connector의.아래 몇 줄의 코드를 통해 추가되었기 때문이다.components 디렉터리에 connector라는 파일이 있습니다.js
/**
* Auto-load bundled components with getters.
*/
fs.readdirSync(__dirname + '/components').forEach(function (filename) {
if (!/\.js$/.test(filename)) {
return;
}
// connector.js, connector
var name = path.basename(filename, '.js');
// bind
var _load = load.bind(null, './components/', name);
Pomelo.components.__defineGetter__(name, _load);
// ,__defineGetter__ , pomelo.getter ,
// _load
Pomelo.__defineGetter__(name, _load);
});
코드에서 볼 수 있듯이 Pomelo가 된다.connector가 방문되었을 때 하나 호출됩니다load 함수.
다음은 이 로드 함수가 무엇을 했는지 다시 한 번 볼까요?load 함수는 실제적으로 Require, 마운트 모듈을 실행했습니다.
function load(path, name) {
if (name) {
return require(path + name);
}
return require(path);
}
하지만load는요, load예요.bind의 결과.실제로는 this 바늘을null로 설정했습니다.bind에 대한 설명:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
여기 있는 Require는 함수를 되돌려주고, Require ('connector ') 는 함수를 되돌려줍니다.코드를 보십시오,conpoment/connector.js에 한 마디가 있어요.
module.exports = function(app, opts) {
return new Component(app, opts);
};
이 함수야말로 앱이다.load가 진정으로 호출하는 함수, 즉pomelo.connector가 되돌아오는 값, 즉 Require가 되돌아오는 값입니다.
그래서
app.load(pomelo.connector, app.get('connectorConfig'));
이 행 코드는 실제로component/connector 모듈을 불러오고 모듈 exports의 함수를 실행하여 설정을 전송하여component를 만듭니다.이 과정은 이미 매우 상세하게 말했기 때문에 관중들이 이해할 수 있을지 없을지는 말할 수 없다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.