-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
File loading #17
base: master
Are you sure you want to change the base?
File loading #17
Changes from 5 commits
2a8c95d
8531bef
730d3c2
afc07d2
705c060
e8fb55d
60a6950
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
var webSocket = require("ws"); | ||
|
||
// A simple websocket abstraction using a emitter/observer pattern | ||
// The api is the same on both the server and the client, but differs in functionality | ||
// | ||
// On the server, channel.send sends the object to all connected clients, while on the client, | ||
// it of course only sends the object to the server | ||
// | ||
// channel.send("type", dataObject); | ||
// channel. on("type", function (receivedDataObject) {...}); | ||
// | ||
// on the client, pass a port (integer, not string) | ||
// on the server, pass an HttpServer | ||
// var channel = new Channel(port || HttpServer); | ||
// | ||
// // client | ||
// channel.on("ping", function (data) { | ||
// data.content === "hi there"; | ||
// channel.send("pong", {content: "hello", ...}); | ||
// }); | ||
// | ||
// // server | ||
// channel.on("pong", function (data) { | ||
// data.content === "hello"; | ||
// channel.send("ping", {content: "hi there", ...}); | ||
// }); | ||
// | ||
// Additionally, you can listen to the websocket's onConnection event | ||
// inside the callback, this refers to the channel. | ||
// channel.onConnection(callback); | ||
function Channel (config) { | ||
var that = this; | ||
this.listeners = Object.create(null); | ||
this.connectionListeners = []; | ||
|
||
function onMessage (message) { | ||
var data = JSON.parse(message.data); | ||
var type = data.type; | ||
|
||
if (type in that.listeners) { | ||
that.listeners[type].forEach(function (listener) { | ||
listener(data); | ||
}); | ||
} else { | ||
console.log("Received a message with type '" + type + "' that's not being listened for."); | ||
} | ||
} | ||
|
||
function onNewConnection(connection) { | ||
console.log("New websocket connection"); | ||
that.connectionListeners.forEach(function (connectionListener) { | ||
connectionListener.call(that, connection); | ||
}); | ||
|
||
// the client is already listening for messages, | ||
if (that.type === "server") { | ||
connection.on("message", onMessage); | ||
} else { | ||
console.log(connection); | ||
} | ||
} | ||
|
||
// on the server side, a channel gets passed an HttpServer, while on the client side it gets passed a port. | ||
// there are small distinctions to make between the server and the client | ||
// the server requires a different websocket constructor, and it talks to multiple clients instead of one. | ||
if (typeof config === "object") { | ||
this.websocket = new webSocket.Server({server: config}); | ||
this.type = "server"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would be tempted to pass the type in as an argument -- that way it's clear at the call sites what kind of channel you are instantiating. It's a little confusing that the type of channel is determined not by the value of any of the arguments, but by the type of the argument. I think passing in the type as a string would make it a bit less confusing. Another approach would be to create a ClientChannel and a ServerChannel constructor, and export only those constructors -- they could call the Channel constructor with the appropriate args. I'm fine with whatever you prefer though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I think the way it currently is feels a little awkward, I don't like different constructors, because It's supposed to be the same api on the server and on the client. Maybe something like this? // client
var channel = new Channel({
type: Channel.server,
httpServer: server
});
// client
var channel = new Channel({
type: Channel.client,
port: 8080
}); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like it. I would just do |
||
} else if (typeof config === "number") { | ||
this.websocket = new webSocket("ws://localhost:" + config + "/editor/"); | ||
this.type = "client"; | ||
} | ||
|
||
// for some reason, the websocket api differs on the client from the server | ||
if (this.type === "server") { | ||
this.websocket.on("connection", onNewConnection); | ||
} else { | ||
this.websocket.open = onNewConnection; | ||
} | ||
|
||
this.websocket.onmessage = onMessage; | ||
} | ||
|
||
Channel.prototype.on = function (messageType, callback) { | ||
if (messageType in this.listeners) { | ||
this.listeners[messageType].push(callback); | ||
} else { | ||
this.listeners[messageType] = [callback]; | ||
} | ||
}; | ||
|
||
Channel.prototype.send = function (messageType, data) { | ||
var message; | ||
|
||
data.type = messageType; | ||
message = JSON.stringify(data); | ||
|
||
// on the server, send to all clients | ||
// on the client, send to the server | ||
if (this.type === "server") { | ||
this.websocket.clients.forEach(function (client) { | ||
client.send(message); | ||
}); | ||
} else { | ||
this.websocket.send(message); | ||
} | ||
}; | ||
|
||
Channel.prototype.onConnection = function(listener) { | ||
this.connectionListeners.push(listener); | ||
}; | ||
|
||
module.exports = Channel; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we just put this file in
lib/
? I'm not sure we need another directory.