I am trying to host my parse server locally, but on my frontend I do not receive any events, not even the 'open' (connection opened) event. I also do not receive any errors that could help me solve the problem.
On my server I am using the following code:
var api = new ParseServer(
{
(... more properties and keys)
liveQuery:
{
classNames: ['Sticky', 'Canvas']
}
});
var app = express();
var mountPath = something;
app.use(mountPath, api);
var httpServer = require('http').createServer(app);
httpServer.listen(port, function(){ console.log('Running on http://localhost:' + port); });
var parseLiveQueryServer = ParseServer.createLiveQueryServer(httpServer);
On the frontend I am using the following code:
const stickyQuery = new Parse.Query(Sticky);
this.stickySubscription = await stickyQuery.subscribe();
console.log(this.stickySubscription); // This gets printed, nothing weird
this.stickySubscription.on('open', () => {
console.log('SUBSCRIPTION: opened'); // This is not printed
});
this.stickySubscription.on('create', (sticky) => {
console.log('SUBSCRIPTION: Sticky created, ', sticky); // This is also not printed
});
this.stickySubscription.on('update', (sticky) => {
console.log('SUBSCRIPTION: Sticky updated, ', sticky); // This is not printed
});
The subscription gets printed, and I don't see anything weird. It seems like connecting with the Parse server is going wrong. Does someone know what I'm missing or doing wrong?
Update: I added the following code to the frontend to show the websocket status and whether error events were triggered, but these events are also not triggered:
this.stickySubscription.on('close', () => {
console.log('SUBSCRIPTION: closed'); // This is not printed
});
Parse.LiveQuery.on('open', () => {
console.log('socket connection established'); // Gets printed
});
Parse.LiveQuery.on('close', () => {
console.log('socket connection closed'); // Is not printed
});
Parse.LiveQuery.on('error', (error) => {
console.log('socket error: ', error); // Is not printed
});
In your subscription query , write your className inside quotations:
const stickyQuery = new Parse.Query('Sticky');
Related
I have 3 components device, server and frontend (admin).
Server
Starts socket.io server with 2 namespaces /admin and /client.
If socket from /admin namespace sends data, server passes it along to /client namespace. If socket from /client namespace sends data, server passes it along to /admin namespace.
const io = require('socket.io');
const device = io.of('/device');
const admin = io.of('/admin');
device.on('connection', (socket) => {
socket.on('data', (data) => {
console.log("PASSING DATA FROM [DEVICE] TO [ADMIN]")
admin.emit('data', data);
})
});
admin.on('connection', (socket) => {
socket.on('data', (data) => {
console.log("PASSING DATA FROM [ADMIN] TO [DEVICE]")
device.emit('data', data);
});
});
io.listen(80);
Device
Uses socket.io-client to connect to socket.io server.
Starts interactive shell session using node-pty.
const io = require('socket.io-client');
const socket = io('http://localhost:80/client');
const os = require('os');
const pty = require('node-pty');
const shell = os.platform() === 'win32' ? 'powershell.exe' : 'bash';
const ptyProcess = pty.spawn(shell, [], {
name: 'xterm-color',
cols: 80,
rows: 30
});
socket.on('connect', () => {
});
// INPUT DATA
socket.on('data', (data) => {
ptyProcess.write(data);
});
// OUTPUTING DATA
ptyProcess.onData = (data) => {
socket.emit('data', data)
}
Frontend
Finally I have the frontend which uses xterm.js to create a terminal inside the browser. I am using vue. The browser client as well connects to socket.io server on the /admin namespace. Basically I have this :
<template>
<div id="app">
<div id="terminal" ref="terminal"></div>
</div>
</template>
<script>
import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
import { io } from 'socket.io-client';
export default {
mounted() {
const term = new Terminal({ cursorBlink : true });
term.open(this.$refs.terminal);
const socket = io('http://localhost:80/admin');
socket.on('connect', () => {
term.write('\r\n*** Connected to backend***\r\n');
term.onData((data) => {
socket.emit('data', data);
})
socket.on('data', (data) => {
term.write(data);
});
socket.on('disconnect', () => {
term.write('\r\n*** Disconnected from backend***\r\n');
});
});
}
}
</script>
Problem
❌ Starting the pty session seems to work, at least there are now errors reported. However it seems the onData listener callback is never fired, even when I ptyProcess.write() something.
❌ Getting input from xterm all the way to the device ptyProcess.write does not seem to work. I can see the data passed along through the socket.io sockets all the way to the device. But from there nothing happens. What do I miss ? Also I don't see my input in the xterm window as well.
After switching from child_process to using node-pty to create an interactive shell session I almost had it right. Following the node-pty documentation it marked the on('data') eventhandler as deprecated. Instead I should use .onData property of the process to register a callback. Like this:
ptyProcess.onData = function(data) {
socket.emit('data', data);
};
But that didn't do anything. So I switched back to the depracated way of adding an event listener:
ptyProcess.on('data', function(data) {
socket.emit('data', data);
});
Now I have a working interactive shell session forwarded from a remote device through websocket inside my browser ✅.
UPDATE
Did more digging for onData property. Realized it's not a property but a method so I used it wrong. This would be the prefered way :
ptyProcess.onData(function(data) {
socket.emit('data', data);
});
Which also works as expected 👍
i am trying to do a very simple real time notification with socket.io. for some reason i can't receive data or fire the event from server to client but from client to server yes. let me show my code:
Client Side
ngOnInit() {
this.socket.on('connect', function (res: any) {
console.log('Socket.io is connected on client side!'); // it shows on client console
});
this.socket.on('alarmsreceived', function (res: any) {
console.log(res + ' i am here now'); // is not firing
});
}
// this method fires from a click button
objectStatus = () => {
this.socket.emit('alarmsystem', 'i am client going to server');
}
Server
var io = require('socket.io').listen(server);
var connections = [];
io.of('/api/v1/monitoring').on('connect', function(socket){
connections.push(socket);
console.log('Connected %s sockets', connections.length); // i see connection on cmd
socket.on('disconnect', function() {
connections.splice(connections.indexOf(socket), 1);
console.log('Connected %s sockets', connections.length);
});
socket.on('alarmsystem', function(res) {
console.log(res); // this shows me the message from client
io.sockets.emit('alarmsreceived', 'I am server heading to client');
});
})
it seems pretty straight forward, but not firing the client event. Can someone help me what i am doing wrong here? Thanks in advance
I have a NodeJS App with Socket Io integration. Now my web page and app both has been implemented but I am facing one issue during execution:
Below is my web page code:
<script>
$(document).ready(function(){
$("#batch")[0].reset();
var socket = io.connect('http://xx.xx.xxx.xx:xxxx',{'forceNew':true });
socket.on('message', function (data) {
var newtext = data;
document.batch.outputtext.value += newtext;
});
socket.on('end', function (data) {
socket.disconnect();
});
});
</script>
And my NodeJS App:
exec_script = function(resp) {
socket.on('connection', function (client) {
console.log('Connection Established');
client.on('disconnect', function () {
console.log('disconnected');
return;
});
var pyshell = new PythonShell('./test.py', options ={ mode: 'text', pythonOptions: ['-u'] });
pyshell.stdout.on('data', function(data) {
client.emit('message', data);
console.log(data);
});
pyshell.end(function(err) {
if (err) throw err;
console.log('End Script');
client.emit('end', 'end');
client.disconnect();
});
});
};
The issue I am facing is that when the Python scripts executes its output is send to browser while my browser status states "Waiting for xx.xx.xxx.xx" and in my FF I see the blue circle circling - that's fine - but even after the Python script has ended and socket disconnected explicitly I still see the browser status as "Waiting for xx.xx.xxx.xx browser title as Connecting with the blue circle rotating?
How can I close and end the connection successfully with the fact that I need the same page in the browser that is I would not navigate the user to some other page?
I tried by using response.end() but the issue I am facing is that if the request data was posted as URL form /today then calling response.end() changes the URL at browser side to http://xx.xx.xxx.xx:xxxx/today leading to a blank / error page which is what I a do not want in my case - the URL should remain as http://xx.xx.xxx.xx:xxxx?
Below is the method I am calling my exec_script method:
router.post('/', function(req, res) {
methods.process(req, res);
});
exports.process = function(req, resp) {
var bname = req.body['date'];
if(typeof req.body['date'] !== "undefined" && req.body['date'] !== null)
{
exec_script(req, resp);
}
};
I have a very simple configuration in a node server with socket.io installed (a little bit more complex but essentially like this one):
var main = require('express')();
server = require('http').createServer(main);
io = require('socket.io')(server);
io.use(function(socket, next) {
console.log("middleware!");
next();
});
io.on('connection', function (socket) {
console.log('connected...');
socket.on('pong', function (data) {
console.log(data.message);
});
setTimeout(function() {
console.log("Saying hello");
socket.emit('ping', { message: 'Hello from server ' + Date.now() });
}, 1000);
});
server.listen(2080, function onCreateServerMain() {
console.log('Server main is listening on port 2080';
console.log('************************************************************');
});
In the client:
var socketIoScript,
loadSocketTimeout,
trialsToLoadSocketIo = 0,
APP_CFG = {baseUrl : "http://192.168.1.13:2080"};
function loadSocketIo(socketIoIp) {
socketIoScript = document.createElement('script');
socketIoScript.setAttribute('src', socketIoIp);
socketIoScript.setAttribute('onload', 'onSocketLoaded();');
document.head.appendChild(socketIoScript);
}
window.onSocketLoaded = function onSocketLoaded() {
if (typeof(io.connect) === 'function') {
var mSocket,
mIoSocket;
$timeout.cancel(loadSocketTimeout);
mIoSocket = new io.Manager(APP_CFG.baseUrl);
mIoSocket.connect(function(socket) {
console.log('Connected!!');
});
mIoSocket.on('error', function onSocketError(e) {
console.log('WebSocket Error ' + error);
});
mIoSocket.on('ping', function onPingReceived(e) {
console.log('Server emitted ping: ' + e.data);
mSocket.emit('pong', 'hi server!');
});
}
}
~(function onLoadSocketTimeout() {
var nextTimeout;
if (trialsToLoadSocketIo < 10) {
nextTimeout = 5000;
} else if (trialsToLoadSocketIo > 60) {
nextTimeout = 60000;
} else {
nextTimeout = 1000 * trialsToLoadSocketIo;
}
if (socketIoScript) {
document.head.removeChild(socketIoScript);
}
loadSocketIo(APP_CFG.baseUrl + '/socket.io/socket.io.js#' + trialsToLoadSocketIo);
loadSocketTimeout = $timeout(onLoadSocketTimeout, nextTimeout);
trialsToLoadSocketIo += 1;
})();
(I'm doing like this because it's mobile app so it may have not connection). I'm testing it with Brackets and Chrome. Server and client are in the same machine. In the app the script is loaded fine and it connects to the server as I can it see in node log (edit: and this is all what I get in the node console):
Server main is listening on port 2080
************************************************************
middleware!
connected...
Saying hello
Edit: in Chrome console I don't get any message, and any breakpoint stops at on listeners. If I stop node, the console for the Chrome immediately starts logging that it has been disconnected:
GET http://192.168.1.13:2080/socket.io/?EIO=3&transport=polling&t=1413066902601-6 net::ERR_CONNECTION_REFUSED
GET http://192.168.1.13:2080/socket.io/?EIO=3&transport=polling&t=1413066906606-7 net::ERR_CONNECTION_REFUSED
But I can't see any incoming message. In the app I don't receive any incoming message. Is there any reason why I could not communicate in this environment even if socket is successfully connected?
EDIT
No app is receiving events sent from the other side. Logs from node show this, logs from Chrome are empty.
EDIT
In Chrome app I don't receive console.log("Connected!");. But neither I receive ERR_CONNECTION_REFUSED errors: I don't receive anything.
EDIT
I managed to get console.log("Connected!"); in the app by changing Manager options:
mIoSocket = new io.Manager(APP_CFG.baseUrl, { autoConnect: false });
As it was auto connecting and the events were attached after connection was made, "Connected" was never reached. But I'm still not receiving any event in any app.
I had a similar issue were event callbacks on the server were not firing when emitting. My event names were ping and pong. As soon as I renamed these events everything worked.
I suspect the event names ping and pong are reserved by socket.io and so cannot be used.
Ok, so a few things :
First, var mSocket doesn't seem to be initialized, so it may be difficult for it to emit() anything (am I missing something?)
Second, when you do :
socket.on('pong', function (data) {
console.log(data.message);
});
the server expects to receive an object containing a message property, eg : data = {message:'hi server'} In your case, you send a string, so data is 'Hi server !' and your log will say 'undefined'. You should change this bit to :
socket.on('pong', function (data) {
console.log(data);
});
and you have a similar problem the other way around, you send an object : { message: 'Hello from server ' + Date.now() }, and are trying to log a data property which does not exist. Change this bit to :
console.log('Server emitted ping: ' + e.message);
And third , you have to listen for events on the socket, not the 'manager'
Client :
mIoSocket.connect(function(socket) {
console.log('Connected!!');
socket.emit('pong');
socket.on('error', function onSocketError(e) {
console.log('WebSocket Error ' + error);
});
socket.on('ping', function onPingReceived(e) {
console.log('Server emitted ping: ' + e.data);
socket.emit('pong', 'hi server!');
});
});
Server :
io.on('connection', function (socket) {
console.log('connected...');
socket.on('pong', function (data) {
console.log(data);
});
setTimeout(function() {
console.log("Saying hello");
socket.emit('ping', { message: 'Hello from server ' + Date.now() });
}, 1000);
});
I wondered if someone could help figure out what I am doing wrong:
My client web page initiates a connection with my server, and listens to a long running process whose state is getting updated in the db by a worker process on another thread, emitting updates back to the browser. I define a socket.io connection in the app.post() method. This is handled by the poll() function below (scroll down a bit past the invite checking code)
However, when a new web client connects, it's messages get added to the previous client's as if there were just one channel. Why isn't there a separate unique channel for each browser?
//Create server
var express = require('express'),
app = express(),
http = require('http'),
server = http.createServer(app),
io = require('socket.io').listen(server);
io.set('log level', 1); // reduce logging
io.configure(function () {
io.set("transports", ["xhr-polling"]);
io.set("polling duration", 10);
});
app.post('/api/users', function (req, res) {
if (!req.body.auth.accessToken) {
req.body.auth.accessToken = req.body.auth.authResponse.accessToken;
} //fb return object is different depending on whether it is a first login or subsequent
logger.log('debug', '/api/users:POST', req.body);
io.sockets.on('connection', function (socket) {
socket = socket;
socket.emit('update', {
status: 200 //send initialization ping
});
//check if user has valid invite, if not try to invite
db.getTotalUserInvites(function (err_inv, res_total) {
db.getUserInvite(req.body.fid, function (err_check, res_check) {
logger.log('debug', 'Total invites issued=' + res_total);
//process report - all we need is accesToken, processReport will do the rest
mine_fb.processUser(req.body.auth.accessToken, socket, function (User,socket) { //pass channel properly
db.getReportStatus(User.fid,socket, function (result,socket) {
logger.log('debug', 'report status', result);
if (result) {
if (socket && (result.report_status == -1)) {
logger.log('debug', 'report already processed. retrieving uniq_id ' + result.uniq_id);
socket.emit('update', {
status: -1,
uniq_id: result.uniq_id
});
return true;
} else {
if (socket && (result.report_status >= 0)) {
logger.log('debug', 'we are in the middle of processing report ' + result.uniq_id);
//in this case we become a listener and not a speaker
function poll(socket) {
db.getReportStatus(User.fid, socket,function (r,socket) {
socket.emit('update', { //!!!! THIS EMITS TO ALL CONNECTED BROWSERS
status: r.report_status,
uniq_id: r.uniq_id
}); //...socket
if ((r.report_status >= 0) && (socket)) {
logger.log('debug', 'polling...');
_.delay(poll, 2000, socket);
}
}); //get rerpot
}; //end poll
socket.on('disconnect', function () {
socket=null;
});
poll(socket);
} // else we're in the middle
} //done checking status
} //end of seq
});
return res.send();
});
});
});
});
});
While it is not clear how to help you I can tell what's going on in your code:
app.post('/api/users', function (req, res) {
// some code
io.sockets.on('connection', function (socket) {
// some code
});
});
Whenever a user POSTs something to /api/users a new handler is attached to io.sockets (that's what .on does). But these handlers are never removed, so each time a new connection is established all attached handlers fire. That's where your broadcasting comes from.
You have to separate app.post(...) from io.sockets.on('connection',...) (they should be independent, both defined at module level, not nested). I'm sure it won't be easy (you will probably have to authenticate a user twice for example) but that's the only reasonable way.
You shouldn't put your io.sockets.on('connection', function (socket) inside the app.post scope.
Just put it outside and try again, it will probably work correctly.
Listening to connexion should be done once when the server starts, not each time a client hits some URL.