react-native-meteor
Version:
Full Meteor Client for React Native
78 lines (72 loc) • 2.47 kB
JavaScript
import EventEmitter from 'wolfy87-eventemitter';
import EJSON from 'ejson';
import './mongo-id'; // Register mongo object ids */
export default class Socket extends EventEmitter {
constructor(SocketConstructor, endpoint) {
super();
this.SocketConstructor = SocketConstructor;
this.endpoint = endpoint;
this.rawSocket = null;
}
send(object) {
if (!this.closing) {
const message = EJSON.stringify(object);
this.rawSocket.send(message);
// Emit a copy of the object, as the listener might mutate it.
this.emit('message:out', EJSON.parse(message));
}
}
open() {
/*
* Makes `open` a no-op if there's already a `rawSocket`. This avoids
* memory / socket leaks if `open` is called twice (e.g. by a user
* calling `ddp.connect` twice) without properly disposing of the
* socket connection. `rawSocket` gets automatically set to `null` only
* when it goes into a closed or error state. This way `rawSocket` is
* disposed of correctly: the socket connection is closed, and the
* object can be garbage collected.
*/
if (this.rawSocket) {
return;
}
this.closing = false;
this.rawSocket = new this.SocketConstructor(this.endpoint);
/*
* Calls to `onopen` and `onclose` directly trigger the `open` and
* `close` events on the `Socket` instance.
*/
this.rawSocket.onopen = () => this.emit('open');
this.rawSocket.onclose = () => {
this.rawSocket = null;
this.emit('close');
this.closing = false;
};
/*
* Calls to `onmessage` trigger a `message:in` event on the `Socket`
* instance only once the message (first parameter to `onmessage`) has
* been successfully parsed into a javascript object.
*/
this.rawSocket.onmessage = message => {
var object;
try {
object = EJSON.parse(message.data);
} catch (ignore) {
// Simply ignore the malformed message and return
return;
}
// Outside the try-catch block as it must only catch JSON parsing
// errors, not errors that may occur inside a "message:in" event
// handler
this.emit('message:in', object);
};
}
close() {
/*
* Avoid throwing an error if `rawSocket === null`
*/
if (this.rawSocket) {
this.closing = true;
this.rawSocket.close();
}
}
}