I am having a difficulty understanding Javascript-style function definitions.
I have a Websocket server:
var WebSocketServer = require('ws').Server,
wss = new WebSocketServer();
wss.on('connection', function (ws) {
ws.on('message', function (message) {
console.log('received: %s from client', message);
})
ws.send('hello client');
})
And I want to send a message to the connected clients when another function importantEvent() is called.
function importantEvent(message) {
//send message to the connected client
ws.send('hello client');
}
What is the good way of calling ws.send() inside importantEvent()?
I use EventEmitter to similar things to avoid a strong module strength.
// eventManager.js
const EventEmitter = require('events');
class EventManager extends EventEmitter {}
const eventManager = new EventManager();
module.exports = eventManager;
// websocket.js
var eventManager = require('eventManager');
var WebSocketServer = require('ws').Server,
wss = new WebSocketServer();
wss.on('connection', function (ws) {
...
})
function broadcast(data, filter) {
wss.clients.forEach( ... // depends on library using to web-socket
}
eventManager.on('my-event', function (arg1, arg2) {
broadcast({arg1, arg2})
});
// in any other files
var eventManager = require('eventManager');
eventManager.emit('my-event', 'hello', 'world');
It's a matter of what clients you want to reach. In wss.on('connection'... event, the ws received by the function is the client that is connecting to the server in this event.
As you want send a message to all the clients connected, you need to use the broadcast method
var WebSocketServer = require('ws').Server,
wss = new WebSocketServer();
function importantEvent(message) {
// Broadcast to all.
wss.broadcast = function broadcast(data) {
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
client.send('hello client');
}
});
};
}
Related
I am trying to make a connection between my React web app and a mosquito broker which runs on docker. To do this i am using a MQTT.js libary.
Here is my code so far:
const mqtt = require('mqtt')
const client = mqtt.connect('tcp://172.19.0.4:1883')
console.log('mounted');
client.on('connect', function () {
console.log('connected')
client.subscribe('/powertest', function (err) {
if (!err) {
// client.publish('presence', 'Hello mqtt')
console.log('error')
}
})
})
client.on('message', function (topic, message) {
// message is Buffer
console.log(message.toString())
// client.end()
})
This code is in the componentDidMount lifecycle event. When I run it, it shows no errors and it does not enter the on connect area. All I see in the console is the "mounted" log message.
How do I make it connect with the broker?
Let's put the subscriber and the publisher in the same file:
var mqtt = require('mqtt')
var client = mqtt.connect('mqtt://test.mosquitto.org')
client.on('connect', function () {
client.subscribe('presence', function (err) {
if (!err) {
client.publish('presence', 'Hello mqtt')
}
})
})
client.on('message', function (topic, message) {
// message is Buffer
console.log(message.toString())
client.end()
})
I'm trying to make a test bot that, upon being chatted to responds with a (meaningless) string gotten from a JSON object through another API
Code:
var restify = require('restify');
var builder = require('botbuilder');
var request = require('request-promise');
// Setup Restify Server
var server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function () {
console.log('%s listening to %s', server.name, server.url);
});
// Create chat connector for communicating with the Bot Framework Service
var connector = new builder.ChatConnector({
appId: process.env.MicrosoftAppId,
appPassword: process.env.MicrosoftAppPassword
});
// Listen for messages from users
server.post('/api/messages', connector.listen());
// Receive messages from the user and respond by echoing each message back (prefixed with 'You said:')
var bot = new builder.UniversalBot(connector, function (session) {
var text = await MyRequest()
session.send("%s", text);
});
async function MyRequest() {
var options = {
uri: "https://jsonplaceholder.typicode.com/posts/1",
method: "GET",
json: true
}
try {
var result = await request(options);
return result;
} catch (err) {
console.error(err);
}
}
The problem is the bot var isn't an asynch function, so I can't put await in it. If I remove await, the bot replies with Object Promise. I'm fairly inexperienced in JS overall, so can I get any pointers?
e: The Request part works great, I've tested it alone in a different js program
Have you tried this. If you are using ES6 compatible Node environment this should work
var bot = new builder.UniversalBot(connector, async function (session) {
// Use JSON.stringify() if MyRequest Promise will resolve a object
var text = await MyRequest()
session.send("%s", text);
});
If async/await isn't possible, how about returning a promise? like below:
function MyRequest() {
var options = {
uri: "https://jsonplaceholder.typicode.com/posts/1",
method: "GET",
json: true
}
return request(options);
}
And use Promise.then to act on the result, like so:
var bot = new builder.UniversalBot(connector, function (session) {
MyRequest().then(function(text) {
session.send("%s", text);
}).catch(function(error) {
session.send("%s", error);
});
});
I got files called socket.js and Chat.js.
Let's say Chat.js contains:
function Chat(io, socket) {
this.sendChatMessage(data) {};
}
module.exports = Chat;
And socket.js
module.exports = function (io) {
io.on('connection', function(socket) {
var Chat = new (require('./Chat'))(io, socket),
});
}
After several tries, the above is the cleanliest way of requiring "Chat" that I've found, but it still looks weird for something so frequently used.
I tried stuff like (still clean I guess)
var Chat = require('./Chat'),
Chat = new Chat(io, socket);
Also tried adding the "new" in module.exports = new Chat; directly etc. etc.
Is there any standard for this? If not, what do you use?
Yup, that's how you do it: export whatever function(s) you need and call them after requiring the module.
Also tried adding the "new" in module.exports = new Chat
Don't do that unless you really want to export an instance and not the constructor.
It's pretty common to use a pattern like this so you could omit the new where you call the constructor:
function Chat(io, socket) {
if (! (this instanceof Chat)) return new Chat(io, socket);
this.sendChatMessage(data) {};
}
var Chat = require('./Chat')(io, socket)
I'm not sure what is most popular now but here is how I might do it with babel and the ES6 standard:
// chat.js
export default class Chat {
constructor(io, socket) {
this.io = io;
this.socket = socket;
this.sendMessage(data);
}
sendMessage(data) {
//
}
}
// iochat.js
import Chat from './chat';
export default function connectChat (io) {
io.on('connection', (socket) => {
let chat = new Chat(io, socket);
});
}
// tio.js
import connectChat from './iochat';
let io = { on:()=>{}};
connectChat(io);
Although I am guessing the connectChat thing is part of a larger module or app.
I am struggling to send a stream of data being consumed via pusher-client-node to the client using Socket.IO.
I am receiving my data in Node.JS like this:
var API_KEY = 'cb65d0a7a72cd94adf1f';
var pusher = new Pusher(API_KEY, {
encrypted: true
});
var channel = pusher.subscribe("ticker.160");
channel.bind("message", function (data) {
//console.log(data);
});
My data, which comes in continuously, looks like that:
{ channel: 'ticker.160',
trade:
{ timestamp: 1420031543,
datetime: '2014-12-31 08:12:23 EST',
marketid: '160',
topsell: { price: '0.00007650', quantity: '106.26697381' }}
My Socket.IO code looks like this:
/**
* Socket.io
*/
var io = require("socket.io").listen(server, {log: true});
var users = [];
var stream = channel.bind("message", function (data) {
console.log(data);
});
io.on("connection", function (socket) {
// The user it's added to the array if it doesn't exist
if(users.indexOf(socket.id) === -1) {
users.push(socket.id);
}
// Log
logConnectedUsers();
socket.emit('someevent', { attr: 'value' } )
stream.on("newdata", function(data) {
// only broadcast when users are online
if(users.length > 0) {
// This emits the signal to the user that started
// the stream
socket.emit('someevent', { attr: 'value' } )
}
else {
// If there are no users connected we destroy the stream.
// Why would we keep it running for nobody?
stream.destroy();
stream = null;
}
});
// This handles when a user is disconnected
socket.on("disconnect", function(o) {
// find the user in the array
var index = users.indexOf(socket.id);
if(index != -1) {
// Eliminates the user from the array
users.splice(index, 1);
}
logConnectedUsers();
});
});
// A log function for debugging purposes
function logConnectedUsers() {
console.log("============= CONNECTED USERS ==============");
console.log("== :: " + users.length);
console.log("============================================");
}
I am quite new to Node.JS and Socket.IO and struggle to use my pusher stream in Node.JS. Therefore my question: How to connect my Socket.IO code with my Pusher code?
You need to use socket/io rooms ...
server:
var channel = pusher.subscribe("ticker.160"); //subscribe to pusher
//pass messages from pusher to the matching room in socket.io
channel.bind("message", function (data) {
io.to('ticker.160').emit('room-message', {room:'ticker.160', data:data});
});
...
io.on("connection", function (socket) {
...
socket.on('join', function(room){
socket.join(room);
});
socket.on('leave', function(room){
socket.leave(room);
});
});
client:
io.emit('join','ticker.160');
io.on('room-message', function(message){
switch(message.room) {
case 'ticker.160': return doSomething(message.data);
...
}
});
var connectionHandler = function(socket) {
var player = null;
socket.on('login', function(data) {
player = {
data: okeyServer.playerJoin(data),
socket: socket
};
socket.emit('welcome');
});
socket.on('info server', function(data) {
var info = okeyServer.Info();
socket.emit('info server', info);
});
socket.on('join game', function (data) {
var gameid = data.gameid;
var side = data.side;
okeyServer.playerJoinGame(player, gameid, side);
});
socket.on('disconnect', function () {
okeyServer.playerLeave(player);
io.sockets.emit('player leave', player);
});
}
I am trying to do a multiplayer game app with socket.io. When player connects, i want a 'login' message to be sent first. and i initialize the player variable for further use.
Other messages uses the player variable later.
How can i make sure client sent a 'login' message before making other requests.
I can check if player is null on every request where i need player but that seems ugly.
You could install the other listeners from within the login listener:
var connectionHandler = function(socket) {
var player = null;
socket.on('login', function(data) {
// If we already have a player, just return a `welcome` message.
if (player !== null) {
return socket.emit('welcome');
}
// Store player.
player = {
data: okeyServer.playerJoin(data),
socket: socket
};
// Emit welcome message.
socket.emit('welcome');
// Set up the rest of the listeners.
socket.on('info server', function(data) {
var info = okeyServer.Info();
socket.emit('info server', info);
});
socket.on('join game', function (data) {
var gameid = data.gameid;
var side = data.side;
okeyServer.playerJoinGame(player, gameid, side);
});
socket.on('disconnect', function () {
okeyServer.playerLeave(player);
io.sockets.emit('player leave', player);
});
});
};
This assumes that a login message is only ever emitted once by the client during the lifetime of the connection. If that's not the case, you need to make some changes.