uniapp,h5

socket.js 27KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.Socket = void 0;
  7. const socket_io_parser_1 = require("socket.io-parser");
  8. const on_js_1 = require("./on.js");
  9. const component_emitter_1 = require("@socket.io/component-emitter");
  10. const debug_1 = __importDefault(require("debug")); // debug()
  11. const debug = (0, debug_1.default)("socket.io-client:socket"); // debug()
  12. /**
  13. * Internal events.
  14. * These events can't be emitted by the user.
  15. */
  16. const RESERVED_EVENTS = Object.freeze({
  17. connect: 1,
  18. connect_error: 1,
  19. disconnect: 1,
  20. disconnecting: 1,
  21. // EventEmitter reserved events: https://nodejs.org/api/events.html#events_event_newlistener
  22. newListener: 1,
  23. removeListener: 1,
  24. });
  25. /**
  26. * A Socket is the fundamental class for interacting with the server.
  27. *
  28. * A Socket belongs to a certain Namespace (by default /) and uses an underlying {@link Manager} to communicate.
  29. *
  30. * @example
  31. * const socket = io();
  32. *
  33. * socket.on("connect", () => {
  34. * console.log("connected");
  35. * });
  36. *
  37. * // send an event to the server
  38. * socket.emit("foo", "bar");
  39. *
  40. * socket.on("foobar", () => {
  41. * // an event was received from the server
  42. * });
  43. *
  44. * // upon disconnection
  45. * socket.on("disconnect", (reason) => {
  46. * console.log(`disconnected due to ${reason}`);
  47. * });
  48. */
  49. class Socket extends component_emitter_1.Emitter {
  50. /**
  51. * `Socket` constructor.
  52. */
  53. constructor(io, nsp, opts) {
  54. super();
  55. /**
  56. * Whether the socket is currently connected to the server.
  57. *
  58. * @example
  59. * const socket = io();
  60. *
  61. * socket.on("connect", () => {
  62. * console.log(socket.connected); // true
  63. * });
  64. *
  65. * socket.on("disconnect", () => {
  66. * console.log(socket.connected); // false
  67. * });
  68. */
  69. this.connected = false;
  70. /**
  71. * Whether the connection state was recovered after a temporary disconnection. In that case, any missed packets will
  72. * be transmitted by the server.
  73. */
  74. this.recovered = false;
  75. /**
  76. * Buffer for packets received before the CONNECT packet
  77. */
  78. this.receiveBuffer = [];
  79. /**
  80. * Buffer for packets that will be sent once the socket is connected
  81. */
  82. this.sendBuffer = [];
  83. /**
  84. * The queue of packets to be sent with retry in case of failure.
  85. *
  86. * Packets are sent one by one, each waiting for the server acknowledgement, in order to guarantee the delivery order.
  87. * @private
  88. */
  89. this._queue = [];
  90. /**
  91. * A sequence to generate the ID of the {@link QueuedPacket}.
  92. * @private
  93. */
  94. this._queueSeq = 0;
  95. this.ids = 0;
  96. /**
  97. * A map containing acknowledgement handlers.
  98. *
  99. * The `withError` attribute is used to differentiate handlers that accept an error as first argument:
  100. *
  101. * - `socket.emit("test", (err, value) => { ... })` with `ackTimeout` option
  102. * - `socket.timeout(5000).emit("test", (err, value) => { ... })`
  103. * - `const value = await socket.emitWithAck("test")`
  104. *
  105. * From those that don't:
  106. *
  107. * - `socket.emit("test", (value) => { ... });`
  108. *
  109. * In the first case, the handlers will be called with an error when:
  110. *
  111. * - the timeout is reached
  112. * - the socket gets disconnected
  113. *
  114. * In the second case, the handlers will be simply discarded upon disconnection, since the client will never receive
  115. * an acknowledgement from the server.
  116. *
  117. * @private
  118. */
  119. this.acks = {};
  120. this.flags = {};
  121. this.io = io;
  122. this.nsp = nsp;
  123. if (opts && opts.auth) {
  124. this.auth = opts.auth;
  125. }
  126. this._opts = Object.assign({}, opts);
  127. if (this.io._autoConnect)
  128. this.open();
  129. }
  130. /**
  131. * Whether the socket is currently disconnected
  132. *
  133. * @example
  134. * const socket = io();
  135. *
  136. * socket.on("connect", () => {
  137. * console.log(socket.disconnected); // false
  138. * });
  139. *
  140. * socket.on("disconnect", () => {
  141. * console.log(socket.disconnected); // true
  142. * });
  143. */
  144. get disconnected() {
  145. return !this.connected;
  146. }
  147. /**
  148. * Subscribe to open, close and packet events
  149. *
  150. * @private
  151. */
  152. subEvents() {
  153. if (this.subs)
  154. return;
  155. const io = this.io;
  156. this.subs = [
  157. (0, on_js_1.on)(io, "open", this.onopen.bind(this)),
  158. (0, on_js_1.on)(io, "packet", this.onpacket.bind(this)),
  159. (0, on_js_1.on)(io, "error", this.onerror.bind(this)),
  160. (0, on_js_1.on)(io, "close", this.onclose.bind(this)),
  161. ];
  162. }
  163. /**
  164. * Whether the Socket will try to reconnect when its Manager connects or reconnects.
  165. *
  166. * @example
  167. * const socket = io();
  168. *
  169. * console.log(socket.active); // true
  170. *
  171. * socket.on("disconnect", (reason) => {
  172. * if (reason === "io server disconnect") {
  173. * // the disconnection was initiated by the server, you need to manually reconnect
  174. * console.log(socket.active); // false
  175. * }
  176. * // else the socket will automatically try to reconnect
  177. * console.log(socket.active); // true
  178. * });
  179. */
  180. get active() {
  181. return !!this.subs;
  182. }
  183. /**
  184. * "Opens" the socket.
  185. *
  186. * @example
  187. * const socket = io({
  188. * autoConnect: false
  189. * });
  190. *
  191. * socket.connect();
  192. */
  193. connect() {
  194. if (this.connected)
  195. return this;
  196. this.subEvents();
  197. if (!this.io["_reconnecting"])
  198. this.io.open(); // ensure open
  199. if ("open" === this.io._readyState)
  200. this.onopen();
  201. return this;
  202. }
  203. /**
  204. * Alias for {@link connect()}.
  205. */
  206. open() {
  207. return this.connect();
  208. }
  209. /**
  210. * Sends a `message` event.
  211. *
  212. * This method mimics the WebSocket.send() method.
  213. *
  214. * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
  215. *
  216. * @example
  217. * socket.send("hello");
  218. *
  219. * // this is equivalent to
  220. * socket.emit("message", "hello");
  221. *
  222. * @return self
  223. */
  224. send(...args) {
  225. args.unshift("message");
  226. this.emit.apply(this, args);
  227. return this;
  228. }
  229. /**
  230. * Override `emit`.
  231. * If the event is in `events`, it's emitted normally.
  232. *
  233. * @example
  234. * socket.emit("hello", "world");
  235. *
  236. * // all serializable datastructures are supported (no need to call JSON.stringify)
  237. * socket.emit("hello", 1, "2", { 3: ["4"], 5: Uint8Array.from([6]) });
  238. *
  239. * // with an acknowledgement from the server
  240. * socket.emit("hello", "world", (val) => {
  241. * // ...
  242. * });
  243. *
  244. * @return self
  245. */
  246. emit(ev, ...args) {
  247. var _a, _b, _c;
  248. if (RESERVED_EVENTS.hasOwnProperty(ev)) {
  249. throw new Error('"' + ev.toString() + '" is a reserved event name');
  250. }
  251. args.unshift(ev);
  252. if (this._opts.retries && !this.flags.fromQueue && !this.flags.volatile) {
  253. this._addToQueue(args);
  254. return this;
  255. }
  256. const packet = {
  257. type: socket_io_parser_1.PacketType.EVENT,
  258. data: args,
  259. };
  260. packet.options = {};
  261. packet.options.compress = this.flags.compress !== false;
  262. // event ack callback
  263. if ("function" === typeof args[args.length - 1]) {
  264. const id = this.ids++;
  265. debug("emitting packet with ack id %d", id);
  266. const ack = args.pop();
  267. this._registerAckCallback(id, ack);
  268. packet.id = id;
  269. }
  270. const isTransportWritable = (_b = (_a = this.io.engine) === null || _a === void 0 ? void 0 : _a.transport) === null || _b === void 0 ? void 0 : _b.writable;
  271. const isConnected = this.connected && !((_c = this.io.engine) === null || _c === void 0 ? void 0 : _c._hasPingExpired());
  272. const discardPacket = this.flags.volatile && !isTransportWritable;
  273. if (discardPacket) {
  274. debug("discard packet as the transport is not currently writable");
  275. }
  276. else if (isConnected) {
  277. this.notifyOutgoingListeners(packet);
  278. this.packet(packet);
  279. }
  280. else {
  281. this.sendBuffer.push(packet);
  282. }
  283. this.flags = {};
  284. return this;
  285. }
  286. /**
  287. * @private
  288. */
  289. _registerAckCallback(id, ack) {
  290. var _a;
  291. const timeout = (_a = this.flags.timeout) !== null && _a !== void 0 ? _a : this._opts.ackTimeout;
  292. if (timeout === undefined) {
  293. this.acks[id] = ack;
  294. return;
  295. }
  296. // @ts-ignore
  297. const timer = this.io.setTimeoutFn(() => {
  298. delete this.acks[id];
  299. for (let i = 0; i < this.sendBuffer.length; i++) {
  300. if (this.sendBuffer[i].id === id) {
  301. debug("removing packet with ack id %d from the buffer", id);
  302. this.sendBuffer.splice(i, 1);
  303. }
  304. }
  305. debug("event with ack id %d has timed out after %d ms", id, timeout);
  306. ack.call(this, new Error("operation has timed out"));
  307. }, timeout);
  308. const fn = (...args) => {
  309. // @ts-ignore
  310. this.io.clearTimeoutFn(timer);
  311. ack.apply(this, args);
  312. };
  313. fn.withError = true;
  314. this.acks[id] = fn;
  315. }
  316. /**
  317. * Emits an event and waits for an acknowledgement
  318. *
  319. * @example
  320. * // without timeout
  321. * const response = await socket.emitWithAck("hello", "world");
  322. *
  323. * // with a specific timeout
  324. * try {
  325. * const response = await socket.timeout(1000).emitWithAck("hello", "world");
  326. * } catch (err) {
  327. * // the server did not acknowledge the event in the given delay
  328. * }
  329. *
  330. * @return a Promise that will be fulfilled when the server acknowledges the event
  331. */
  332. emitWithAck(ev, ...args) {
  333. return new Promise((resolve, reject) => {
  334. const fn = (arg1, arg2) => {
  335. return arg1 ? reject(arg1) : resolve(arg2);
  336. };
  337. fn.withError = true;
  338. args.push(fn);
  339. this.emit(ev, ...args);
  340. });
  341. }
  342. /**
  343. * Add the packet to the queue.
  344. * @param args
  345. * @private
  346. */
  347. _addToQueue(args) {
  348. let ack;
  349. if (typeof args[args.length - 1] === "function") {
  350. ack = args.pop();
  351. }
  352. const packet = {
  353. id: this._queueSeq++,
  354. tryCount: 0,
  355. pending: false,
  356. args,
  357. flags: Object.assign({ fromQueue: true }, this.flags),
  358. };
  359. args.push((err, ...responseArgs) => {
  360. if (packet !== this._queue[0]) {
  361. // the packet has already been acknowledged
  362. return;
  363. }
  364. const hasError = err !== null;
  365. if (hasError) {
  366. if (packet.tryCount > this._opts.retries) {
  367. debug("packet [%d] is discarded after %d tries", packet.id, packet.tryCount);
  368. this._queue.shift();
  369. if (ack) {
  370. ack(err);
  371. }
  372. }
  373. }
  374. else {
  375. debug("packet [%d] was successfully sent", packet.id);
  376. this._queue.shift();
  377. if (ack) {
  378. ack(null, ...responseArgs);
  379. }
  380. }
  381. packet.pending = false;
  382. return this._drainQueue();
  383. });
  384. this._queue.push(packet);
  385. this._drainQueue();
  386. }
  387. /**
  388. * Send the first packet of the queue, and wait for an acknowledgement from the server.
  389. * @param force - whether to resend a packet that has not been acknowledged yet
  390. *
  391. * @private
  392. */
  393. _drainQueue(force = false) {
  394. debug("draining queue");
  395. if (!this.connected || this._queue.length === 0) {
  396. return;
  397. }
  398. const packet = this._queue[0];
  399. if (packet.pending && !force) {
  400. debug("packet [%d] has already been sent and is waiting for an ack", packet.id);
  401. return;
  402. }
  403. packet.pending = true;
  404. packet.tryCount++;
  405. debug("sending packet [%d] (try n°%d)", packet.id, packet.tryCount);
  406. this.flags = packet.flags;
  407. this.emit.apply(this, packet.args);
  408. }
  409. /**
  410. * Sends a packet.
  411. *
  412. * @param packet
  413. * @private
  414. */
  415. packet(packet) {
  416. packet.nsp = this.nsp;
  417. this.io._packet(packet);
  418. }
  419. /**
  420. * Called upon engine `open`.
  421. *
  422. * @private
  423. */
  424. onopen() {
  425. debug("transport is open - connecting");
  426. if (typeof this.auth == "function") {
  427. this.auth((data) => {
  428. this._sendConnectPacket(data);
  429. });
  430. }
  431. else {
  432. this._sendConnectPacket(this.auth);
  433. }
  434. }
  435. /**
  436. * Sends a CONNECT packet to initiate the Socket.IO session.
  437. *
  438. * @param data
  439. * @private
  440. */
  441. _sendConnectPacket(data) {
  442. this.packet({
  443. type: socket_io_parser_1.PacketType.CONNECT,
  444. data: this._pid
  445. ? Object.assign({ pid: this._pid, offset: this._lastOffset }, data)
  446. : data,
  447. });
  448. }
  449. /**
  450. * Called upon engine or manager `error`.
  451. *
  452. * @param err
  453. * @private
  454. */
  455. onerror(err) {
  456. if (!this.connected) {
  457. this.emitReserved("connect_error", err);
  458. }
  459. }
  460. /**
  461. * Called upon engine `close`.
  462. *
  463. * @param reason
  464. * @param description
  465. * @private
  466. */
  467. onclose(reason, description) {
  468. debug("close (%s)", reason);
  469. this.connected = false;
  470. delete this.id;
  471. this.emitReserved("disconnect", reason, description);
  472. this._clearAcks();
  473. }
  474. /**
  475. * Clears the acknowledgement handlers upon disconnection, since the client will never receive an acknowledgement from
  476. * the server.
  477. *
  478. * @private
  479. */
  480. _clearAcks() {
  481. Object.keys(this.acks).forEach((id) => {
  482. const isBuffered = this.sendBuffer.some((packet) => String(packet.id) === id);
  483. if (!isBuffered) {
  484. // note: handlers that do not accept an error as first argument are ignored here
  485. const ack = this.acks[id];
  486. delete this.acks[id];
  487. if (ack.withError) {
  488. ack.call(this, new Error("socket has been disconnected"));
  489. }
  490. }
  491. });
  492. }
  493. /**
  494. * Called with socket packet.
  495. *
  496. * @param packet
  497. * @private
  498. */
  499. onpacket(packet) {
  500. const sameNamespace = packet.nsp === this.nsp;
  501. if (!sameNamespace)
  502. return;
  503. switch (packet.type) {
  504. case socket_io_parser_1.PacketType.CONNECT:
  505. if (packet.data && packet.data.sid) {
  506. this.onconnect(packet.data.sid, packet.data.pid);
  507. }
  508. else {
  509. this.emitReserved("connect_error", new Error("It seems you are trying to reach a Socket.IO server in v2.x with a v3.x client, but they are not compatible (more information here: https://socket.io/docs/v3/migrating-from-2-x-to-3-0/)"));
  510. }
  511. break;
  512. case socket_io_parser_1.PacketType.EVENT:
  513. case socket_io_parser_1.PacketType.BINARY_EVENT:
  514. this.onevent(packet);
  515. break;
  516. case socket_io_parser_1.PacketType.ACK:
  517. case socket_io_parser_1.PacketType.BINARY_ACK:
  518. this.onack(packet);
  519. break;
  520. case socket_io_parser_1.PacketType.DISCONNECT:
  521. this.ondisconnect();
  522. break;
  523. case socket_io_parser_1.PacketType.CONNECT_ERROR:
  524. this.destroy();
  525. const err = new Error(packet.data.message);
  526. // @ts-ignore
  527. err.data = packet.data.data;
  528. this.emitReserved("connect_error", err);
  529. break;
  530. }
  531. }
  532. /**
  533. * Called upon a server event.
  534. *
  535. * @param packet
  536. * @private
  537. */
  538. onevent(packet) {
  539. const args = packet.data || [];
  540. debug("emitting event %j", args);
  541. if (null != packet.id) {
  542. debug("attaching ack callback to event");
  543. args.push(this.ack(packet.id));
  544. }
  545. if (this.connected) {
  546. this.emitEvent(args);
  547. }
  548. else {
  549. this.receiveBuffer.push(Object.freeze(args));
  550. }
  551. }
  552. emitEvent(args) {
  553. if (this._anyListeners && this._anyListeners.length) {
  554. const listeners = this._anyListeners.slice();
  555. for (const listener of listeners) {
  556. listener.apply(this, args);
  557. }
  558. }
  559. super.emit.apply(this, args);
  560. if (this._pid && args.length && typeof args[args.length - 1] === "string") {
  561. this._lastOffset = args[args.length - 1];
  562. }
  563. }
  564. /**
  565. * Produces an ack callback to emit with an event.
  566. *
  567. * @private
  568. */
  569. ack(id) {
  570. const self = this;
  571. let sent = false;
  572. return function (...args) {
  573. // prevent double callbacks
  574. if (sent)
  575. return;
  576. sent = true;
  577. debug("sending ack %j", args);
  578. self.packet({
  579. type: socket_io_parser_1.PacketType.ACK,
  580. id: id,
  581. data: args,
  582. });
  583. };
  584. }
  585. /**
  586. * Called upon a server acknowledgement.
  587. *
  588. * @param packet
  589. * @private
  590. */
  591. onack(packet) {
  592. const ack = this.acks[packet.id];
  593. if (typeof ack !== "function") {
  594. debug("bad ack %s", packet.id);
  595. return;
  596. }
  597. delete this.acks[packet.id];
  598. debug("calling ack %s with %j", packet.id, packet.data);
  599. // @ts-ignore FIXME ack is incorrectly inferred as 'never'
  600. if (ack.withError) {
  601. packet.data.unshift(null);
  602. }
  603. // @ts-ignore
  604. ack.apply(this, packet.data);
  605. }
  606. /**
  607. * Called upon server connect.
  608. *
  609. * @private
  610. */
  611. onconnect(id, pid) {
  612. debug("socket connected with id %s", id);
  613. this.id = id;
  614. this.recovered = pid && this._pid === pid;
  615. this._pid = pid; // defined only if connection state recovery is enabled
  616. this.connected = true;
  617. this.emitBuffered();
  618. this.emitReserved("connect");
  619. this._drainQueue(true);
  620. }
  621. /**
  622. * Emit buffered events (received and emitted).
  623. *
  624. * @private
  625. */
  626. emitBuffered() {
  627. this.receiveBuffer.forEach((args) => this.emitEvent(args));
  628. this.receiveBuffer = [];
  629. this.sendBuffer.forEach((packet) => {
  630. this.notifyOutgoingListeners(packet);
  631. this.packet(packet);
  632. });
  633. this.sendBuffer = [];
  634. }
  635. /**
  636. * Called upon server disconnect.
  637. *
  638. * @private
  639. */
  640. ondisconnect() {
  641. debug("server disconnect (%s)", this.nsp);
  642. this.destroy();
  643. this.onclose("io server disconnect");
  644. }
  645. /**
  646. * Called upon forced client/server side disconnections,
  647. * this method ensures the manager stops tracking us and
  648. * that reconnections don't get triggered for this.
  649. *
  650. * @private
  651. */
  652. destroy() {
  653. if (this.subs) {
  654. // clean subscriptions to avoid reconnections
  655. this.subs.forEach((subDestroy) => subDestroy());
  656. this.subs = undefined;
  657. }
  658. this.io["_destroy"](this);
  659. }
  660. /**
  661. * Disconnects the socket manually. In that case, the socket will not try to reconnect.
  662. *
  663. * If this is the last active Socket instance of the {@link Manager}, the low-level connection will be closed.
  664. *
  665. * @example
  666. * const socket = io();
  667. *
  668. * socket.on("disconnect", (reason) => {
  669. * // console.log(reason); prints "io client disconnect"
  670. * });
  671. *
  672. * socket.disconnect();
  673. *
  674. * @return self
  675. */
  676. disconnect() {
  677. if (this.connected) {
  678. debug("performing disconnect (%s)", this.nsp);
  679. this.packet({ type: socket_io_parser_1.PacketType.DISCONNECT });
  680. }
  681. // remove socket from pool
  682. this.destroy();
  683. if (this.connected) {
  684. // fire events
  685. this.onclose("io client disconnect");
  686. }
  687. return this;
  688. }
  689. /**
  690. * Alias for {@link disconnect()}.
  691. *
  692. * @return self
  693. */
  694. close() {
  695. return this.disconnect();
  696. }
  697. /**
  698. * Sets the compress flag.
  699. *
  700. * @example
  701. * socket.compress(false).emit("hello");
  702. *
  703. * @param compress - if `true`, compresses the sending data
  704. * @return self
  705. */
  706. compress(compress) {
  707. this.flags.compress = compress;
  708. return this;
  709. }
  710. /**
  711. * Sets a modifier for a subsequent event emission that the event message will be dropped when this socket is not
  712. * ready to send messages.
  713. *
  714. * @example
  715. * socket.volatile.emit("hello"); // the server may or may not receive it
  716. *
  717. * @returns self
  718. */
  719. get volatile() {
  720. this.flags.volatile = true;
  721. return this;
  722. }
  723. /**
  724. * Sets a modifier for a subsequent event emission that the callback will be called with an error when the
  725. * given number of milliseconds have elapsed without an acknowledgement from the server:
  726. *
  727. * @example
  728. * socket.timeout(5000).emit("my-event", (err) => {
  729. * if (err) {
  730. * // the server did not acknowledge the event in the given delay
  731. * }
  732. * });
  733. *
  734. * @returns self
  735. */
  736. timeout(timeout) {
  737. this.flags.timeout = timeout;
  738. return this;
  739. }
  740. /**
  741. * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
  742. * callback.
  743. *
  744. * @example
  745. * socket.onAny((event, ...args) => {
  746. * console.log(`got ${event}`);
  747. * });
  748. *
  749. * @param listener
  750. */
  751. onAny(listener) {
  752. this._anyListeners = this._anyListeners || [];
  753. this._anyListeners.push(listener);
  754. return this;
  755. }
  756. /**
  757. * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
  758. * callback. The listener is added to the beginning of the listeners array.
  759. *
  760. * @example
  761. * socket.prependAny((event, ...args) => {
  762. * console.log(`got event ${event}`);
  763. * });
  764. *
  765. * @param listener
  766. */
  767. prependAny(listener) {
  768. this._anyListeners = this._anyListeners || [];
  769. this._anyListeners.unshift(listener);
  770. return this;
  771. }
  772. /**
  773. * Removes the listener that will be fired when any event is emitted.
  774. *
  775. * @example
  776. * const catchAllListener = (event, ...args) => {
  777. * console.log(`got event ${event}`);
  778. * }
  779. *
  780. * socket.onAny(catchAllListener);
  781. *
  782. * // remove a specific listener
  783. * socket.offAny(catchAllListener);
  784. *
  785. * // or remove all listeners
  786. * socket.offAny();
  787. *
  788. * @param listener
  789. */
  790. offAny(listener) {
  791. if (!this._anyListeners) {
  792. return this;
  793. }
  794. if (listener) {
  795. const listeners = this._anyListeners;
  796. for (let i = 0; i < listeners.length; i++) {
  797. if (listener === listeners[i]) {
  798. listeners.splice(i, 1);
  799. return this;
  800. }
  801. }
  802. }
  803. else {
  804. this._anyListeners = [];
  805. }
  806. return this;
  807. }
  808. /**
  809. * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
  810. * e.g. to remove listeners.
  811. */
  812. listenersAny() {
  813. return this._anyListeners || [];
  814. }
  815. /**
  816. * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
  817. * callback.
  818. *
  819. * Note: acknowledgements sent to the server are not included.
  820. *
  821. * @example
  822. * socket.onAnyOutgoing((event, ...args) => {
  823. * console.log(`sent event ${event}`);
  824. * });
  825. *
  826. * @param listener
  827. */
  828. onAnyOutgoing(listener) {
  829. this._anyOutgoingListeners = this._anyOutgoingListeners || [];
  830. this._anyOutgoingListeners.push(listener);
  831. return this;
  832. }
  833. /**
  834. * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
  835. * callback. The listener is added to the beginning of the listeners array.
  836. *
  837. * Note: acknowledgements sent to the server are not included.
  838. *
  839. * @example
  840. * socket.prependAnyOutgoing((event, ...args) => {
  841. * console.log(`sent event ${event}`);
  842. * });
  843. *
  844. * @param listener
  845. */
  846. prependAnyOutgoing(listener) {
  847. this._anyOutgoingListeners = this._anyOutgoingListeners || [];
  848. this._anyOutgoingListeners.unshift(listener);
  849. return this;
  850. }
  851. /**
  852. * Removes the listener that will be fired when any event is emitted.
  853. *
  854. * @example
  855. * const catchAllListener = (event, ...args) => {
  856. * console.log(`sent event ${event}`);
  857. * }
  858. *
  859. * socket.onAnyOutgoing(catchAllListener);
  860. *
  861. * // remove a specific listener
  862. * socket.offAnyOutgoing(catchAllListener);
  863. *
  864. * // or remove all listeners
  865. * socket.offAnyOutgoing();
  866. *
  867. * @param [listener] - the catch-all listener (optional)
  868. */
  869. offAnyOutgoing(listener) {
  870. if (!this._anyOutgoingListeners) {
  871. return this;
  872. }
  873. if (listener) {
  874. const listeners = this._anyOutgoingListeners;
  875. for (let i = 0; i < listeners.length; i++) {
  876. if (listener === listeners[i]) {
  877. listeners.splice(i, 1);
  878. return this;
  879. }
  880. }
  881. }
  882. else {
  883. this._anyOutgoingListeners = [];
  884. }
  885. return this;
  886. }
  887. /**
  888. * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
  889. * e.g. to remove listeners.
  890. */
  891. listenersAnyOutgoing() {
  892. return this._anyOutgoingListeners || [];
  893. }
  894. /**
  895. * Notify the listeners for each packet sent
  896. *
  897. * @param packet
  898. *
  899. * @private
  900. */
  901. notifyOutgoingListeners(packet) {
  902. if (this._anyOutgoingListeners && this._anyOutgoingListeners.length) {
  903. const listeners = this._anyOutgoingListeners.slice();
  904. for (const listener of listeners) {
  905. listener.apply(this, packet.data);
  906. }
  907. }
  908. }
  909. }
  910. exports.Socket = Socket;