PageRenderTime 68ms CodeModel.GetById 38ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/socket.js

https://github.com/taoyuan/musher.js
JavaScript | 140 lines | 111 code | 26 blank | 3 comment | 18 complexity | eb1eb14a3cf3e9153a1af8e42a3e54ae MD5 | raw file
  1. "use strict";
  2. var debug = require('debug')('musher:socket');
  3. var utils = require('./utils');
  4. var Emitter = require('./emitter');
  5. var Channels = require('./channels');
  6. var defaultHost = 'musher.io';
  7. module.exports = Socket;
  8. function Socket(adapter, opts) {
  9. if (!(this instanceof Socket)) {
  10. return new Socket(adapter, opts);
  11. }
  12. // just save everything we get
  13. var settings = this.settings = utils.assign({ host: defaultHost }, opts);
  14. this.key = settings.key;
  15. this.prefix = this.key ? '$' + this.key + ':' : null;
  16. var useSSL = settings.ssl || settings.secure;
  17. if (useSSL !== null && useSSL !== undefined) {
  18. settings.useSSL = !!useSSL;
  19. }
  20. settings.options = settings.options || {};
  21. this.queue = [];
  22. // initialize adapter
  23. adapter.initialize(this, utils);
  24. // we have an adapter now?
  25. if (!this.adapter) {
  26. throw new Error('Adapter is not defined correctly: it should create `adapter` member of socket');
  27. }
  28. this.channels = new Channels(this);
  29. var socket = this;
  30. this.adapter.on('error', function () {
  31. socket.emit('error')
  32. });
  33. this.adapter.on('connect', function () {
  34. socket._connected();
  35. });
  36. this.adapter.on('close', function () {
  37. socket._close();
  38. });
  39. this.adapter.on('message', function (topic, message, packet) {
  40. socket._message(topic, message);
  41. });
  42. }
  43. Emitter.extend(Socket);
  44. Socket.prototype.__defineGetter__('connected', function () {
  45. return this.adapter.connected;
  46. });
  47. Socket.prototype._connected = function () {
  48. for (var i = 0; i < this.queue.length; i++) {
  49. this.queue[i]();
  50. }
  51. this.queue = [];
  52. this.emit('connected');
  53. };
  54. Socket.prototype._close = function () {
  55. this.emit('close');
  56. };
  57. Socket.prototype._enqueue = function (fn) {
  58. this.queue.push(fn);
  59. };
  60. Socket.prototype._message = function (topic, message) {
  61. this.channels._handleMessage(topic, message);
  62. };
  63. Socket.prototype._wrap = function (topic) {
  64. return this.prefix && topic.indexOf(this.prefix) !== 0 ? this.prefix + topic : topic;
  65. };
  66. Socket.prototype._unwrap = function (topic) {
  67. return this.prefix && topic.indexOf(this.prefix) === 0 ? topic.substring(this.prefix.length) : topic;
  68. };
  69. Socket.prototype.ready = function (fn) {
  70. if (this.connected) return fn();
  71. this._enqueue(fn);
  72. };
  73. Socket.prototype.close = function (cb) {
  74. if (cb) this.once('close', cb);
  75. this.adapter.close();
  76. };
  77. Socket.prototype.channel = function (name) {
  78. return this.channels.find(name);
  79. };
  80. Socket.prototype.subscribe = function (name, opts, cb) {
  81. if (typeof opts === "function") {
  82. cb = opts;
  83. opts = null;
  84. }
  85. var channel = this.channels.add(name, this);
  86. this.ready(function () {
  87. channel.subscribe(opts, cb);
  88. });
  89. return channel;
  90. };
  91. Socket.prototype.unsubscribe = function (name, cb) {
  92. cb = cb || utils.nop;
  93. var channel = this.channels.remove(name, cb);
  94. if (channel.connected) {
  95. channel.unsubscribe(cb);
  96. } else {
  97. cb();
  98. }
  99. return this;
  100. };
  101. Socket.prototype.publish = function (topic, event, data) {
  102. var socket = this;
  103. this.ready(function () {
  104. socket._publish(topic, event, data);
  105. });
  106. return this;
  107. };
  108. Socket.prototype._publish = function (topic, event, data) {
  109. if (!topic) throw new Error('`topic` must not be null');
  110. if (!event) throw new Error('`event` must not be null');
  111. if (!data) throw new Error('`data` must not be null');
  112. var message = JSON.stringify({__event__: event, __data__: data});
  113. this.adapter.publish(this._wrap(topic), message);
  114. };