UNPKG

silk-gui

Version:

GUI for developers and Node OS

204 lines (186 loc) 5.84 kB
var doAsync; if(typeof module != "undefined"){ var RSVP = require("rsvp"); var StreamPromise = require(__dirname+"/StreamPromise.js"); var EventEmitter = require("events").EventEmitter; doAsync = process.nextTick.bind(process); }else{ doAsync = function(fn){ setTimeout(fn,1); }; } /** An io listener that sends messages to the functions wanting to handle them. @interface @augments EventEmitter @param {function} wSendFn - Function that will be called when you wish to write something to a target. */ function MessageWriter(wSendFn){ EventEmitter.call(this); this.on = this.addListener.bind(this); this.off = this.removeListener.bind(this); if(typeof this.getListeners == "undefined"){ this.getListeners = this.listeners.bind(this); } this.wSendFn = wSendFn; this.queue = []; this._ready = false; // method calls that are sent and waiting an answer } MessageWriter.prototype = Object.create(EventEmitter.prototype); MessageWriter.prototype.constructor = MessageWriter; /** The method that is called when the MessageWriter writes. @abstract @memberof MessageWriter @param {object} message - The response message @param {object} user - that transport method that was given to us by {@link MessageRouter#RouteMessage}. @return {undefined} */ MessageWriter.prototype.wSendFn = function(message,user){ throw new Error("this message is abstract and needs to be overwritten"); }; /** Allows the MessageWriter to know when it can start sending messages @function @memberof MessageWriter */ MessageWriter.prototype.ready = function(){ this._ready = true; while(this.queue.length > 0){ this.wSendFn(this.queue.shift()); } return this; }; /** Allows the MessageWriter to know when they it can no longer send messages @function @memberof MessageWriter */ MessageWriter.prototype.stop = function(){ this._ready = false; }; /** The message to call after you have transformed the data into a readable form @function @memberof MessageWriter @param {object} message - An object containing important message information */ MessageWriter.prototype.returnMessage = function (message) { if (this.getListeners(message.id).length === 0) throw new Error("non Existant Message"); this.emit(message.id, message.error,message.data); }; /** Sends a message to the io without expecting a return @function @memberof MessageWriter @param {string} name - the namespace you want to process your data @param {object} data - the data you want to send them */ MessageWriter.prototype.trigger = function(name,data){ this.messageFactory("trigger",name).send(data); }; /** `requestCallback` is what will be called once an io is completed. @callback requestCallback @param {error} error - an error if one exists @param {object} response message - the response that the target gave back */ /** Sends a message to the io expecting one return value @function @memberof MessageWriter @param {string} key - the namespace you want to process your data @param {object} data - the data you want to send them @param {requestCallback} [cb] - If no callback is defined, it will return a promise @returns {this|Promise} Returns a promise if no callback is defined */ MessageWriter.prototype.get = function (name, data, cb) { // save callback so we can call it when receiving the reply var ret; if(typeof cb == "undefined"){ ret = RSVP.defer(); ret.promise.done = ret.promise.then.bind(ret.promise); cb = function(err, message){ if(err) return ret.reject(err); ret.resolve(message); }; } this.messageFactory("get", name, cb).send(data); return (ret)?ret.promise:this; }; /** Sends one or more messages to the io expecting one or more return values @function @memberof MessageWriter @param {string} key - the namespace you want to process your data @param {...object} [data] - as many data arguments you want to send right away @param {requestCallback} [cb] - If no callback or data is defined, it will return a {@link StreamPromise} @returns {this|StreamPromise} Returns a {@link StreamPromise} if no callback is defined */ MessageWriter.prototype.pipe = function(name, callback){ var ret; var args = []; if(arguments.length > 2){ args = Array.prototype.slice.call(arguments, 0); callback = args.pop(); name = args.shift(); }else if(arguments.length == 1){ ret = new StreamPromise(); callback = ret._write.bind(ret); } var p = this.messageFactory("pipe", name, callback); while(args.length > 0) p.send(args.shift()); if(ret){ ret.inherit(p.send.bind(p)); return ret; } return p; }; /** Aborts a pipe or get request @function @memberof MessageWriter @param {StreamPromise|string} key - the namespace or promise you want to stop @returns {this} To allow chaining */ MessageWriter.prototype.abort = function(ob){ if(!ob) throw Error("cannot unpipe "+ob); var id = (ob.id)?ob.id:ob; if(this.listeners(id).length === 0) throw new Error("Cannot abort what doesn't exist"); this.removeAllListeners(id); return this; }; MessageWriter.prototype.messageFactory = function(type,name,callback){ //id to find callback when returned data is received var id = Date.now() + "-" + Math.random(); var content = { id: id, name: name, type: type, }; content.send = function(data){ var clone = JSON.parse(JSON.stringify(content)); clone.data = data; if(this._ready){ this.wSendFn(clone); }else{ //if there is an error queue it for later when socket connects this.queue.push(clone); } }.bind(this); if(type == "trigger") return content; if(type == "get") this.once(id,callback); if(type == "pipe") this.addListener(id,callback); return content; }; if(typeof module != "undefined"){ module.exports = MessageWriter; }