JAVASCRIPT 186
Socket.js Guest on 17th April 2021 09:55:13 AM
  1.  
  2. /**
  3.  * Module dependencies.
  4.  */
  5.  
  6. var parser = require('socket.io-parser');
  7. var Emitter = require('component-emitter');
  8. var toArray = require('to-array');
  9. var on = require('./on');
  10. var bind = require('component-bind');
  11. var debug = require('debug')('socket.io-client:socket');
  12. var hasBin = require('has-binary');
  13.  
  14. /**
  15.  * Module exports.
  16.  */
  17.  
  18. module.exports = exports = Socket;
  19.  
  20. /**
  21.  * Internal events (blacklisted).
  22.  * These events can't be emitted by the user.
  23.  *
  24.  * @api private
  25.  */
  26.  
  27. var events = {
  28.   connect: 1,
  29.   connect_error: 1,
  30.   connect_timeout: 1,
  31.   connecting: 1,
  32.   disconnect: 1,
  33.   error: 1,
  34.   reconnect: 1,
  35.   reconnect_attempt: 1,
  36.   reconnect_failed: 1,
  37.   reconnect_error: 1,
  38.   reconnecting: 1,
  39.   ping: 1,
  40.   pong: 1
  41. };
  42.  
  43. /**
  44.  * Shortcut to `Emitter#emit`.
  45.  */
  46.  
  47. var emit = Emitter.prototype.emit;
  48.  
  49. /**
  50.  * `Socket` constructor.
  51.  *
  52.  * @api public
  53.  */
  54.  
  55. function Socket (io, nsp, opts) {
  56.   this.io = io;
  57.   this.nsp = nsp;
  58.   this.json = this; // compat
  59.   this.ids = 0;
  60.   this.acks = {};
  61.   this.receiveBuffer = [];
  62.   this.sendBuffer = [];
  63.   this.connected = false;
  64.   this.disconnected = true;
  65.   if (opts && opts.query) {
  66.     this.query = opts.query;
  67.   }
  68.   if (this.io.autoConnect) this.open();
  69. }
  70.  
  71. /**
  72.  * Mix in `Emitter`.
  73.  */
  74.  
  75. Emitter(Socket.prototype);
  76.  
  77. /**
  78.  * Subscribe to open, close and packet events
  79.  *
  80.  * @api private
  81.  */
  82.  
  83. Socket.prototype.subEvents = function () {
  84.   if (this.subs) return;
  85.  
  86.   var io = this.io;
  87.   this.subs = [
  88.     on(io, 'open', bind(this, 'onopen')),
  89.     on(io, 'packet', bind(this, 'onpacket')),
  90.     on(io, 'close', bind(this, 'onclose'))
  91.   ];
  92. };
  93.  
  94. /**
  95.  * "Opens" the socket.
  96.  *
  97.  * @api public
  98.  */
  99.  
  100. Socket.prototype.open =
  101. Socket.prototype.connect = function () {
  102.   if (this.connected) return this;
  103.  
  104.   this.subEvents();
  105.   this.io.open(); // ensure open
  106.   if ('open' === this.io.readyState) this.onopen();
  107.   this.emit('connecting');
  108.   return this;
  109. };
  110.  
  111. /**
  112.  * Sends a `message` event.
  113.  *
  114.  * @return {Socket} self
  115.  * @api public
  116.  */
  117.  
  118. Socket.prototype.send = function () {
  119.   var args = toArray(arguments);
  120.   args.unshift('message');
  121.   this.emit.apply(this, args);
  122.   return this;
  123. };
  124.  
  125. /**
  126.  * Override `emit`.
  127.  * If the event is in `events`, it's emitted normally.
  128.  *
  129.  * @param {String} event name
  130.  * @return {Socket} self
  131.  * @api public
  132.  */
  133.  
  134. Socket.prototype.emit = function (ev) {
  135.   if (events.hasOwnProperty(ev)) {
  136.     emit.apply(this, arguments);
  137.     return this;
  138.   }
  139.  
  140.   var args = toArray(arguments);
  141.   var parserType = parser.EVENT; // default
  142.   if (hasBin(args)) { parserType = parser.BINARY_EVENT; } // binary
  143.   var packet = { type: parserType, data: args };
  144.  
  145.   packet.options = {};
  146.   packet.options.compress = !this.flags || false !== this.flags.compress;
  147.  
  148.   // event ack callback
  149.   if ('function' === typeof args[args.length - 1]) {
  150.     debug('emitting packet with ack id %d', this.ids);
  151.     this.acks[this.ids] = args.pop();
  152.     packet.id = this.ids++;
  153.   }
  154.  
  155.   if (this.connected) {
  156.     this.packet(packet);
  157.   } else {
  158.     this.sendBuffer.push(packet);
  159.   }
  160.  
  161.   delete this.flags;
  162.  
  163.   return this;
  164. };
  165.  
  166. /**
  167.  * Sends a packet.
  168.  *
  169.  * @param {Object} packet
  170.  * @api private
  171.  */
  172.  
  173. Socket.prototype.packet = function (packet) {
  174.   packet.nsp = this.nsp;
  175.   this.io.packet(packet);
  176. };
  177.  
  178. /**
  179.  * Called upon engine `open`.
  180.  *
  181.  * @api private
  182.  */
  183.  
  184. Socket.prototype.onopen = function () {
  185.   debug('transport is open - connecting');
  186.  
  187.   // write connect packet if necessary
  188.   if ('/' !== this.nsp) {
  189.     if (this.query) {
  190.       this.packet({type: parser.CONNECT, query: this.query});
  191.     } else {
  192.       this.packet({type: parser.CONNECT});
  193.     }
  194.   }
  195. };
  196.  
  197. /**
  198.  * Called upon engine `close`.
  199.  *
  200.  * @param {String} reason
  201.  * @api private
  202.  */
  203.  
  204. Socket.prototype.onclose = function (reason) {
  205.   debug('close (%s)', reason);
  206.   this.connected = false;
  207.   this.disconnected = true;
  208.   delete this.id;
  209.   this.emit('disconnect', reason);
  210. };
  211.  
  212. /**
  213.  * Called with socket packet.
  214.  *
  215.  * @param {Object} packet
  216.  * @api private
  217.  */
  218.  
  219. Socket.prototype.onpacket = function (packet) {
  220.   if (packet.nsp !== this.nsp) return;
  221.  
  222.   switch (packet.type) {
  223.     case parser.CONNECT:
  224.       this.onconnect();
  225.       break;
  226.  
  227.     case parser.EVENT:
  228.       this.onevent(packet);
  229.       break;
  230.  
  231.     case parser.BINARY_EVENT:
  232.       this.onevent(packet);
  233.       break;
  234.  
  235.     case parser.ACK:
  236.       this.onack(packet);
  237.       break;
  238.  
  239.     case parser.BINARY_ACK:
  240.       this.onack(packet);
  241.       break;
  242.  
  243.     case parser.DISCONNECT:
  244.       this.ondisconnect();
  245.       break;
  246.  
  247.     case parser.ERROR:
  248.       this.emit('error', packet.data);
  249.       break;
  250.   }
  251. };
  252.  
  253. /**
  254.  * Called upon a server event.
  255.  *
  256.  * @param {Object} packet
  257.  * @api private
  258.  */
  259.  
  260. Socket.prototype.onevent = function (packet) {
  261.   var args = packet.data || [];
  262.   debug('emitting event %j', args);
  263.  
  264.   if (null != packet.id) {
  265.     debug('attaching ack callback to event');
  266.     args.push(this.ack(packet.id));
  267.   }
  268.  
  269.   if (this.connected) {
  270.     emit.apply(this, args);
  271.   } else {
  272.     this.receiveBuffer.push(args);
  273.   }
  274. };
  275.  
  276. /**
  277.  * Produces an ack callback to emit with an event.
  278.  *
  279.  * @api private
  280.  */
  281.  
  282. Socket.prototype.ack = function (id) {
  283.   var self = this;
  284.   var sent = false;
  285.   return function () {
  286.     // prevent double callbacks
  287.     if (sent) return;
  288.     sent = true;
  289.     var args = toArray(arguments);
  290.     debug('sending ack %j', args);
  291.  
  292.     var type = hasBin(args) ? parser.BINARY_ACK : parser.ACK;
  293.     self.packet({
  294.       type: type,
  295.       id: id,
  296.       data: args
  297.     });
  298.   };
  299. };
  300.  
  301. /**
  302.  * Called upon a server acknowlegement.
  303.  *
  304.  * @param {Object} packet
  305.  * @api private
  306.  */
  307.  
  308. Socket.prototype.onack = function (packet) {
  309.   var ack = this.acks[packet.id];
  310.   if ('function' === typeof ack) {
  311.     debug('calling ack %s with %j', packet.id, packet.data);
  312.     ack.apply(this, packet.data);
  313.     delete this.acks[packet.id];
  314.   } else {
  315.     debug('bad ack %s', packet.id);
  316.   }
  317. };
  318.  
  319. /**
  320.  * Called upon server connect.
  321.  *
  322.  * @api private
  323.  */
  324.  
  325. Socket.prototype.onconnect = function () {
  326.   this.connected = true;
  327.   this.disconnected = false;
  328.   this.emit('connect');
  329.   this.emitBuffered();
  330. };
  331.  
  332. /**
  333.  * Emit buffered events (received and emitted).
  334.  *
  335.  * @api private
  336.  */
  337.  
  338. Socket.prototype.emitBuffered = function () {
  339.   var i;
  340.   for (i = 0; i < this.receiveBuffer.length; i++) {
  341.     emit.apply(this, this.receiveBuffer[i]);
  342.   }
  343.   this.receiveBuffer = [];
  344.  
  345.   for (i = 0; i < this.sendBuffer.length; i++) {
  346.     this.packet(this.sendBuffer[i]);
  347.   }
  348.   this.sendBuffer = [];
  349. };
  350.  
  351. /**
  352.  * Called upon server disconnect.
  353.  *
  354.  * @api private
  355.  */
  356.  
  357. Socket.prototype.ondisconnect = function () {
  358.   debug('server disconnect (%s)', this.nsp);
  359.   this.destroy();
  360.   this.onclose('io server disconnect');
  361. };
  362.  
  363. /**
  364.  * Called upon forced client/server side disconnections,
  365.  * this method ensures the manager stops tracking us and
  366.  * that reconnections don't get triggered for this.
  367.  *
  368.  * @api private.
  369.  */
  370.  
  371. Socket.prototype.destroy = function () {
  372.   if (this.subs) {
  373.     // clean subscriptions to avoid reconnections
  374.     for (var i = 0; i < this.subs.length; i++) {
  375.       this.subs[i].destroy();
  376.     }
  377.     this.subs = null;
  378.   }
  379.  
  380.   this.io.destroy(this);
  381. };
  382.  
  383. /**
  384.  * Disconnects the socket manually.
  385.  *
  386.  * @return {Socket} self
  387.  * @api public
  388.  */
  389.  
  390. Socket.prototype.close =
  391. Socket.prototype.disconnect = function () {
  392.   if (this.connected) {
  393.     debug('performing disconnect (%s)', this.nsp);
  394.     this.packet({ type: parser.DISCONNECT });
  395.   }
  396.  
  397.   // remove socket from pool
  398.   this.destroy();
  399.  
  400.   if (this.connected) {
  401.     // fire events
  402.     this.onclose('io client disconnect');
  403.   }
  404.   return this;
  405. };
  406.  
  407. /**
  408.  * Sets the compress flag.
  409.  *
  410.  * @param {Boolean} if `true`, compresses the sending data
  411.  * @return {Socket} self
  412.  * @api public
  413.  */
  414.  
  415. Socket.prototype.compress = function (compress) {
  416.   this.flags = this.flags || {};
  417.   this.flags.compress = compress;
  418.   return this;
  419. };

Paste-bin is for source code and general debugging text.

Login or Register to edit, delete and keep track of your pastes and more.

Raw Paste

Login or Register to edit or fork this paste. It's free.