Im using web sockets in my AngularJS application.
When a user logs out the web socket connection is closed by the client.
I need to reconnect the web socket when the user logs back on.
The web socket is contained within a service (code is simplified a bit):
angular.module('myApp').factory("SubscriptionFactory", function () {
var Service = {};
var ws = new WebSocket("ws://127.0.0.1:8000");
/* WS methods (onopen, onmessage ect) left out for simplicity */
Service.reestablishConnection = function() {
// Reestablishing connection
ws = new WebSocket("ws://127.0.0.1:8000");
}
return Service;
The problem is that the new instance of the web socket does not work.
According to this question the web socket needs to reattach its handlers to the object when its recreated.
But a AngularJS service is a singleton (and should stay a singleton according to this question).
How can I recreate the web socket instance inside my AngularJS singleton service?
I found the solution myself. It was actually pretty simple:
angular.module('myApp').factory("SubscriptionFactory", function () {
var Service = {};
var ws;
Service.onMessage = function(message) { /* some code */};
Service.onClose = function() { /* some code */ };
Service.onOpen = function() { /* some code */};
Service.onError = function(error) { /* some code */};
Service.connect = function() {
// (Re)connect
ws = new WebSocket("ws://127.0.0.1:8000");
// Reattaching handlers to object
ws.onmessage = Service.onMessage;
ws.onclose = Service.onClose;
ws.onopen = Service.onOpen;
ws.onerror = Service.onError;
}
return Service;
What happens here is simple: Im creating a new Web Socket object and manually attaching the Web Sockets handlers to my AngularJS service.
Related
I'm trying to write a chrome extension that reads a websocket now I have the problem that every message that is sent creates a new websocket, but I do not quite understand why is this a logical error or is it something else, my code:
const OriginalWebsocket = window.WebSocket
const ProxiedWebSocket = function() {
const ws = new OriginalWebsocket(...arguments)
ws.addEventListener("message", function (e) {
// Only intercept
console.log(e.data)
})
return ws;
};
window.WebSocket = ProxiedWebSocket;
I have successfully opened a websocket connection in server to an external API to get exchange ticker data but not sure how to continuously push the data to client / AngularJS.
Here is the router code:
router.get('/live-ticker', function(req, res) {
var autobahn = require('autobahn');
var wsuri = "wss://api.poloniex.com";
var connection = new autobahn.Connection({
url: wsuri,
realm: "realm1"
});
connection.onopen = function(session) {
function tickerEvent(args, kwargs) {
res.json(args);
console.log(args);
}
session.subscribe('ticker', tickerEvent);
}
connection.onclose = function() {
console.log("Websocket connection closed");
}
connection.open();
});
What I'm attemping to do is to have the data from tickerEvent live update the controller in the front end:
app.controller('liveTickerController', function($scope, $http) {
$scope.ticker = [];
var request = $http.get('/live-ticker');
request.success(function(ticker) {
console.log(ticker); //only logging data once
$scope.liveTicker = ticker;
});
request.error(function(err) {
console.log('Error: ' + err);
});
});
How would get live updates pushed to client?
Thank you
you need to push data from the server periodically.
to get these "live updates" on the client side, a plain ajax call is not enough,
you need a realtime communication.
You should use websoket even here, with socket.io and angular socket.io for example you can handle this communication easily
I have been searching for two days now looking for a solution that might work for me. Sadly I have only seen examples and guides on how to setup a websocket server (that sends messages back and forth to clients) and a websocket client (that resides in browser). None of these really work for me, and I am not sure how to achieve what I want here.
Basically I have the following websocket:
require('dotenv').config()
const WebSocket = require('ws');
var connection = new WebSocket('ws://XXX');
connection.onopen = function () {
connection.send(JSON.stringify({"authenticate":process.env.API}));
connection.send(JSON.stringify({"XXX":"YYY"}));
connection.send(JSON.stringify({
"db" : "unique_id",
"query" : {
"table" : "users"
}
}));
};
connection.onerror = function (error) {
console.log('WebSocket Error ' + error);
};
connection.onmessage = function (e) {
console.log('Server: ' + e.data);
var myResponse = JSON.parse(e.data);
var qList = myResponse.results;
};
What I want to do is have my nodeJS-script running, for example an express script with a html page, that also includes the response from onmessage. Why I am complicating this instead of just using the websocket client-side is that I cannot send my auth-code publicly.
Hope I have been clear enough, let me know if you are unsure of my question!
PS. If you think I would be better off using another websocket-script such as Socket.io - I have been looking at them and have not gotten much wiser sadly.
You have a lot of options. Probably the easiest is to export the connection. At the bottom of the file, e.g. module.exports = connection
Then in the express application, import the connection, e.g. const connection = require('./path/connection');
Then make a function that calls itself at a given interval and sends the appropriate message.
Then within the Express app you can use something like connection.on('message', (data, flags) => // do stuff);
Your other option is to create a store object. E.g.
// ./store.js
class store {
constructor() {
this.wsMaterial = {};
}
add(wsInfo) {
this.wsMaterial[key] = wsInfo
}
get store() {
return this.wsMaterial
}
}
module.exports = new store()
Then import the store and updated it, e.g.
// ./websocket file
const store = require('./store');
...
connection.onmessage = function (e) {
console.log('Server: ' + e.data);
var myResponse = JSON.parse(e.data);
var qList = myResponse.results;
store.add(qList)
};
Then from Express...
// ./express.js
const store = require('./store');
store.get // all of your stuff;
I'm trying to recreate the functionality of a hardware serial server with Node and it's actually working, but I'm getting errors from socket instances that have been closed.
Here's a simplified version of the app to show what I'm doing...
var net = require('net');
var SerialPort = require('serialport');
var connectionCounter = 0;
var port = new SerialPort('/dev/ttyUSB0', function () {
var server = net.createServer();
server.on('connection',function(socket) {
connectionCounter++;
var connNumber = connectionCounter;
socket.on('error', function () {
console.log('socket ' + connNumber + ' errored');
});
socket.on('data', function(data) {
port.write(data);
});
port.on('data', function(data) {
socket.write(data);
});
});
server.listen(8887, '127.0.0.1');
}
});
So the first chunk of code that's sent into the 8887 port works fine, and it returns the data back out through the socket. The errors start on the second chunk. In the example, I'm keeping a count of the socket instances and outputting the socket instance number with the error. So as the program runs, the number of sockets instances keeps going up. The most recent instance will eventually handle the data, but I can't figure out what I need to delete to clean up all of the previous socket instances so they'll stop trying to process the incoming data.
I've tried socket.end() and socket.destroy(), but those don't seem to work . Do I need to go as far as deleting the server itself and recreating it?
If anyone ever finds this and cares about what was going wrong, I was setting an event listener on the serialport object every time a new net socket was created. So even though I was deleting the socket every time it was closed, the serialport listener was trying to send data to all of the old deleted sockets. So the solution was to removeListeners from the serialport object upon closing the net socket.
you can use array for storing sockets later on you can delete. this is sample code hope you got the idea
var net = require('net');
var SerialPort = require('serialport');
var connectionCounter = 0;
var mySockets = [];
var port = new SerialPort('/dev/ttyUSB0', function () {
var server = net.createServer();
server.on('connection',function(socket) {
mySockets.push(socket);
connectionCounter++;
var connNumber = connectionCounter;
socket.on('error', function () {
console.log('socket ' + connNumber + ' errored');
});
socket.on('data', function(data) {
port.write(data);
});
port.on('data', function(data) {
socket.write(data);
});
});
server.listen(8887, '127.0.0.1');
}
//get the sockets you want to delete
var s = mySockets.pop();
s = null;
});
this.startServer = function(socket) {
var client = new Client();
client.socket = socket;
clients.push(client);
// Handle incoming messages from clients.
socket.on('data', bind(this.onSocketDataReceive, this));
}
this.onSocketDataReceive = function(data) {
this.commandManager(client, data+"");
}
In this example binding solves the visibility of this, but client is not visible in onSocketDataReceive function, any ideas? if I try to pass client with bind as well, then this becomes invisible...