pomelo源码解析之compnent组件启动

本文详细解析了Pomelo框架中组件的自动加载与启动过程,包括组件的加载方式、启动流程及核心代码解释。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

pomelo中的各个功能模块都是以component组件的形式封装的。例如sessionService,channelService等等。
接下来我们来看component如何被启动,废话不多说,直接上源码。

/**
 * Auto-load bundled components with getters.
 */
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);
});

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

  Pomelo.filters.__defineGetter__(name, _load);
  Pomelo.__defineGetter__(name, _load);
});

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

  Pomelo.rpcFilters.__defineGetter__(name, _load);
});

首先我们应该了解pomelo.js这个文件的具体作用—初始化所有的配置信息和自动加载所有组件,上面的code就是将所有component已文件名做为name,文件加载得到的function作为value,保存在pomelo对象中。

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;
};

之后通过上面的代码,将pomelo中的组件,执行component = component(this, opts);得到组件具体对象,并将对象保存在this.components中 “this.components[name] = component;”。 此处的this就是app = pomelo.createApp();中的app对象。到此为止,app对象中已经保存了我们所有需要component’组件,之后通过start函数,将每一个组件function调用得到组件对象并调用每一个组件对象的start函数。请大家往下看。

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() {
    appUtil.loadDefaultComponents(self);
    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();
    }
  });
};

此函数为application中的启动函数,有pomelo继承,当我们在app.js中做app.start()时,就是调用的此函数。
此处我们需要了解两个函数appUtil.loadDefaultComponents(self); 和 appUtil.optComponents。
让我们先来看loadDefaultComponents:

module.exports.loadDefaultComponents = function(app) {
  var pomelo = require('../pomelo');
  // load system default components
    logger.debug('lv:', pomelo)
  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'));
};

不知道还记不记得上面讲到的,pomelo根据文件名自动加载所有组件,我们可以看到app.load函数的第一个参数是不是在pomelo/lib/component目录下都有这个文件名。事实上,第一个参数就是一个组件函数,有兴趣的还可以去看下app.load的具体实现。总之在这里就将所有的组件函数做了调用得到了组件对象保存在app.components当中。

接下来我们来看optComponents函数:

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) {
      if(typeof err === 'string') {
        logger.error('fail to operate component, method: %s, err: %j', method, err);
      } else {
        logger.error('fail to operate component, method: %s, err: %j',  method, err.stack);
      }
    }
    utils.invokeCallback(cb, err);
  });
};

然后我们来看optComponents这个函数的代码compmethod; 此处就是重点。相信大家已经猜到Constants.RESERVED.START 变量就是‘start’字符串。到了这里pomelo的component启动方式。非常清楚。

我们可以查看pomelo的lib/componets目录下所有的文件都是固定的格式,都存在有start()函数,来作为启动函数。

柚子显示您访问的商户网站可用的优惠券代码,优惠和返现机会。 有什么建议? 柚是一个扩展,安装在您的浏览器,并允许您节省您的购买金额和恢复您的订单(现金返还)的金额的百分比。 它是如何工作的? 当Pomelo扩展程序检测到您在合作伙伴商家网站上时闪烁。当您点击柚子图标优惠券代码时,会显示交易和返现机会。 不要错过兑换优惠券的机会!保存并在网上购物赚钱,而不改变你的习惯。 我该怎么办? 没有或几乎没有。柚子扩展在您的互联网浏览器中自动运行。只要下载柚子扩展。 当您在返现合作伙伴网站(例如:amazon.fr,ebay.fr,...)进行购买时,您的付款将自动记入您的帐户。 请务必通过扩展程序直接连接到您的帐户,以便我们为您指定销售。一旦登录,即使关闭浏览器或关闭计算机,会话仍保持活动状态。 如何付款 当您的柚子延期可用的信贷达到最低5欧元时,您可以通过贝宝或银行转账进行付款申请。柚子还为您提供部分或全部捐赠给慈善机构的可能性。 您的付款由柚子快速处理。 什么是柚子的捐助者和慈善计划? 当您提出付款申请时,柚子会让您有机会捐款给支持的协会。 柚子鼓励慷慨的手势,把你的捐款加倍到你选择的慈善机构。例如,你向癌症研究协会捐赠10欧元,柚子将支付总额20欧元!您通过电子邮件收到确认捐款押金。 没有义务,您选择是要捐款还是要求付款,柚子会以相同的速度处理捐款和付款请求。 支持语言:Français
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值