im learning to use Nuxt in the past i have worked with socket.io and vue but this time i am using nuxt-socket-io
https://nuxt-socket-io.netlify.app/
My problem is that I cannot send events from client to server
here an example:
in socket-io-server.js
io.emit ("eventTry")
at homepage.vue
mounted () {
this.socket = this. $ nuxtSocket ({
name: "main",
});
this.socket.on ("eventTry", () => {
console.log ("this Work Good");
})
},
and this works fine
but when I try to send from the client to the server nothing works example:
at homepage.vue
this.socket.emit ("eventTryClient");
and in socket-io-serve.js:
io.on ("eventTryClient", () => {
console.log ("something should happen here")
})
and this DONT WORK
I've really looked everywhere and I can't find a solution to this problem that should be so simple, could someone help me? I need to have a bidirectional communication, which is the best of socket.io I think
Thanks in advance for your help <3
You need to listen for events on the socket. Listening on a namespace, e.g. your io variable, won't actually listen to events sent by the client. More info here, although it doesn't explicitly state to listen on the client socket.
I do not know where I saw this solution, but I will share it because surely there is someone else who is interested in this... The only thing necessary to establish the connection between client and server is the following:
in your client (example homepage.vue):
import io from "socket.io-client";
const ioClient = io.connect("http://localhost:3001"); // replace it with the url of your socket
The URL it's in nuxt.config.js, and you probably have something like this:
// socket.io configuration
io: {
sockets: [{
default: true, // make this the default socket
name: 'main', // give it a name that we can later use to choose this socket in the .vue file
url: 'http://localhost:3001' // URL wherever your socket IO server runs
}]
},
With this you can use ioClient as your connection on the client for example:
ioClient.on("connect", () => {
console.log("socket-io-client conected")
ioClient.emit('chatmessage', this.message); //now this works and you can receive it on your server normally
})
I dont know if this is the better way to do that, but i dont really saw solutions for this in the documentation ... maybe im blind, or no body answer that
Related
I'm trying to use socket.io to connect to this websocket api:
https://www.cryptocompare.com/api/#-api-web-socket-
(wss://streamer.cryptocompare.com)
I guess im not really understanding socket.io very much.
I created a blank html document:
<!doctype html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.slim.js"></script>
</head>
<body>
<div id="data-show">
</div>
<button id="connect-sock">Connect</button>
<button id="disconnect-sock">DISConnect</button>
</body>
<script src="index.js"></script>
</html>
index.js:
var socket = io('wss://streamer.cryptocompare.com')
console.log('connected')
var btn = document.getElementById('connect-sock')
var btn2 = document.getElementById('disconnect-sock')
var show = document.getElementById('data-show')
//I also tried adding an event listener to a button so when i clicked it, it would do this:
socket.emit('SubAdd', { subs: ['0~Poloniex~BTC~USD'] } )
//Same result of nothing.
socket.on('SubAdd', function(data){
console.log(data)
})
server.js:
var express = require('express')
var socket = require('socket.io')
var app = express()
var server = app.listen(4000, function(){
console.log("well met")
})
app.use(express.static('public'))
var io = socket(server)
io.on('connection', function(socket){
console.log('well met from socket connection', socket.id)
})
server.js is in a file named 'socket-test'. index.html and index.js are in 'socket-test/public/'
so for some reason, in server.js, socket.id will not log to console. its as if this function is being skipped over. but when i change the address in index.js to http://localhost:4000, i get socket.id in console... not sure whats going on there.
Edit: I rarely get socket id when using the wss://streamer.cryptocompare.com/ , sometimes I do, most of the time i dont. It usually works when I switch to localhost, run the server, stop the server, then switch back to the streamer, but if i reload, i dont get socket.id anymore.
I thought that all I was asking it to do here was emit subs to wss://streamer.cryptocompare then console.log(data) that it returns after emitting the subs.
am I missing something here?
Sorry in advance if its blatantly obvious that I'm missing something. I've only known about socket.io for maybe 3 days now, and only today have I watched a basic tutorial on youtube.
You don't need the Express code because in this case the server you want to talk to is on the cryptocompare server -- not a local server. This is captured in your code when you initialize the io object in the HTML file.
Of course, you could still use Node to talk to the cryptocompare websockets API if you're more comfortable with Node. But then you wouldn't need the in-browser JavaScript. Either way, what you need is to create some kind of client in any runtime that speaks websockets and can talk to the cryptocompare websockets API.
With regard to the code being skipped over -- you're right! It is. socket.io is an event driven WebSockets framework. This means that clients register their interest in certain kinds of events/messages, and when those are triggered special functions known as callbacks are called.
If it helps, you can think of those events like channels in a chat room -- if you're not in the right room, you won't see the messages for that room. So you'll need to know what messages you should be listening for, register your interest in those, and register callback functions for each one.
Thankfully cryptocompare has provided client code examples that should help you get an idea for the kinds of messages you should be listening for.
See here
I am trying to create an app that uses websockets, but am running into the dreaded "multiple connection" issue where everytime the page is reloaded rather than closing and reopening a new websocket, another connection is simply added to the list. My question is if anyone knows the best/proper way to close a Socket.io websocket from Angular 2/4+.
Here's what I have as far as code:
service.ts
getUserSocket(userID: string): Observable<any> {
return new Observable(_Observer => {
// Setup the socket namespace subscription
this.UserSocket = io(NTC_API_URL + `/user/${userID}`, { secure: true });
this.UserSocket.on('message', _Message => {
console.log(_Message);
})
})
}
closeUserSocket() {
this.UserSocket.disconnect();
this.UserSocket.close();
}
component.ts
ngOninit() {
// Setup the User Socket
this.UserSocket = this._UsersService.getUserSocket(this.currentUser.userID)
.subscribe(_UserSocketMessage => {
console.log(_UserSocketMessage);
})
}
ngOnDestroy() {
this.UserSocket.unsubscribe();
this._UsersService.closeUserSocket();
}
This doesn't seem to be working as I can still watch the connections pile up just by logging in an out of the application which I have confirmed calls the component to be destroyed.
Another option I tried was using the once listener instead of the on listener, which worked, but I am unsure about the side effects and have read several places that it's not necessarily a fix for not closing the connection, which I can understand.
After quite a bit of tinkering and research it occurred to me that web sockets are made to be resilient. In other words, since they were engineered to reconnect if possible, focusing on disconnect and close was the wrong approach. It was far easier to enforce policies with regard to the Creation of web socket connections.
For starters, I had to refactor a few things on the server side to make sure particular namespaces were only initialized once. This wasn't achieved so much by altering initialization code as it was by making sure that web socket initialization only occurred in places that either only happened on startup, or during processes that are only highly likely to happen once such as a particular user being created.
On the angular side it was also pretty straightforward in that all I had to do was assign the socket to a property within the service, then check if it existed before making the socket connection. Hence only creating the connection if no connection existed previously.
service.ts
// Setup the socket namespace subscription
if (!this.UserSocket) {
// Initialize user permissions socket
this.UserSocket = io(NTC_API_URL + `/user/${this.LocalUser.userID}`, { secure: true });
}
I'm able to send socket.io connections from my extension to my server, but I cannot hear emits from my server inside my extension. I've found conflicting answers regarding this question:
Opening a Socket.IO connection in a google chrome extension says this can't be done; and
Cross-domain connection in Socket.IO says it can.
Is there any special configuration I must change in order to accept emits from my socket server?
EDIT:
(Note: I'm using AngularJS, but it shouldn't be relevant to this question)
socketFactory.js:
myApp.factory('socketFactory', function($rootScope) {
var socket = io.connect('//dev.mydomain.com', {'path': '/api/socket'});
return socket;
}
inject.js:
var packetData = { 'some':'data', 'roomId':'123abc' };
socketFactory.emit('room:join', packetData);
...
socketFactory.on('room:update', function (data) {
console.log('Received data from socket server');
console.log(data)
}
socket.js (server-side):
socket.on('room:join', function ( data ) {
// Setting socketId to detect disconnect
data.user.socketId = socket.id;
socket.join( data.roomId, function() {
// Some code ...
io.sockets.to(data.roomId).emit('room:update', {'some':'data', 'roomId': '123abc'});
}
});
That's the basic setup of my connection. This system works perfectly when I launch the app in non-extension mode (we're making an extension to emulate our webapp), but when in the extension, room:update is never triggered.
EDIT 2:
We did a console.log on the socket object (generated on connect) in socket.js. Inside the headers, it appears the host is dev.mydomain.com, while the referrer is www.othersite.com. Could this be the problem? What does "host" refer to? Host of the socket server, or host of the socket listener? In the latter case, it would make sense it's not reaching www.othersite.com over which we have the extension running.
EDIT 3: ...And it started working out of nowhere. Must be a race condition somewhere. Closing the question as no longer relevant.
It suddenly works. Probably a race condition.
Im trying to set up a node.js server to send messages to the client, which will then display the messages using a jquery notification library, I'm using this notifcation library if anyone's interested: http://needim.github.com/noty/
At the minute I have a postgres database set up with a table which has a a trigger on it to write to a listener.
The trigger is as follows:
CREATE OR REPLACE FUNCTION new_noti() RETURNS trigger AS $$
DECLARE
BEGIN
PERFORM pg_notify('watchers', TG_TABLE_NAME || ',msg,' || NEW.msg );
RETURN new;
END;
$$ LANGUAGE plpgsql;
Then I have a node.js server as follows:
var pg = require ('pg');
var pgConString = "pg://aydin:password#localhost/test"
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, url = require('url')
app.listen(8080);
function handler (request, respsonse) {
var client = new pg.Client(pgConString);
client.connect();
client.query('LISTEN "watchers"');
client.on('notification', function(msg) {
console.log(msg.payload);
sendMessage(msg.payload);
});
}
function sendMessage(message) {
io.sockets.emit('notification', {'message': message});
}
Then I have some client code as follows:
<script type="text/javascript">
var socket = io.connect('http://localhost:8080');
socket.on('notification', function (data) {
console.log(data.message);
newNoty(data);
});
function newNoty(data) {
noty({
"text":data.message,
buttons: [{
type: 'button green',
text: 'Go to'
}],
"theme":"noty_theme_twitter",
"layout":"bottomRight",
"type":"information",
"animateOpen":{
"height":"toggle"
},
"animateClose":{
"height":"toggle"
},
"speed":500,
"timeout":7500,
"closeButton":true,
"closeOnSelfClick":true,
"closeOnSelfOver":false,
"modal":false,
});
}
</script>
This doesn't work, it seems the node.js never receives the postgres notifications, I think this is because I am using the function handler and I'm not actually firing any requests to it from the client code. I'm not sure how to do this and whether it is the correct way?
Is there a function on which can fire on connections and not requests?
And am I even doing it the right way round? should there be a server on the client side which node.js sends messages to? How does it know when a client is available? Any help or pointers to tutorials would be much appreciated. Thankyou.
You're not actually setting up your database connection until the client sends an HTTP request. It looks like that may never happen due to same-origin issues (your client code appears to be coming from somewhere other than the server you've shown).
In any case, you probably want to set up the connection in response to a "connection" event from io.sockets (i.e. move the stuff that's currently in the HTTP request handler there). That's how it "knows when a client is available". Or maybe you should be doing it as part of initialization. Your client-side code seems OK, but it's out of context so it's hard to tell whether it really fits your needs.
I need to know what transport method a client is using for some conditional statements on the nodeJS serverside.
Does anyone know how I can get that information? Is it held within the client object?
As of Socket.IO 1.0:
Client:
socket.on('connect', function() {
console.log(socket.io.engine.transport.name);
}
Server:
io.sockets.on('connection', function(socket) {
console.log(socket.conn.transport.name);
}
In socket.io 0.7.6
io.sockets.on('connection', function(client) {
console.log(io.transports[client.id].name);
});
April 2012, this works: socket.transport
I'm sure you can find it if you dig in the internals of a client object, although without knowing why you need this I have to recommend against this kind of check for 2 reasons:
Firstly, since it isn't in the API the developers have absolutely no responsibility to keep things backward compatible, so any given version might implement/store that information differently, which will only ripple into your own development and cause problems.
Secondly, and more importantly, I suggest you rethink your design, the communication with the server thru socket.io is built to be transparent to the method being used. There should be no difference on either side. That's the purpose of the library, designing an app that behaves otherwise is totally orthogonal to that idea.
for reference's sake and google stumbles:-
in case anyone is still using v0.9 (or possibly earlier)
you can access this info from client side like this:
var socket = io.connect();
console.log(socket.socket.transport.name); //log the name of the transport being used.
answer found on google groups https://groups.google.com/forum/#!topic/socket_io/yx_9wJiiAg0
I believe this will solve your problem. My trick here is to save the transport type on the HTTP Request object once the client connects. You can then pick it up in your callback later. First we tweak the Listener class:
var io = require('socket.io'),
io.Listener.prototype._onConnectionOld = io.Listener.prototype._onConnection;
io.Listener.prototype._onConnection = function(transport, req, res, up, head){
req.socketIOTransport = transport; // Take note of the transport type
this._onConnectionOld.call(this, transport, req, res, up, head);
};
And then below in the body of your app:
var socket = io.listen(app),
socket.on('connection', function(client){
console.log(client.request.socketIOTransport); // Lets check that transport
// ...
});
Hope this helps!
io.connect.managers['connect url/port'].engine.transport