CFWEBSOCKET - unable to call websocket object in Javascript - javascript

I'm using the cfwebsocket tag in Coldfusion to create a web socket connection.
I looked at an example from here http://www.sagarganatra.com/2012/03/html5-websockets-in-coldfusion-10.html
and near the end it shows you all the javascript calls you can make on the web socket object.
However, when I try to make any call on it I get an error that it is undefined.
For example I have:
<cfwebsocket name="ws" onMessage="messageHandler" onOpen="openHandler" onClose="closeHandler" onError="errorHandler" subscribeTo="chat" />
and in my javascript i call
alert(ws.isConnectionOpen());
and I get the error in firebug: TypeError: ws is undefined.
Anyone know why I can't call it?
My chat works fine and I can connect and chat properly. I just wanted to close the connection when the chat ended so I was looking into how it's done calling the websocket but I don't know why it's not working.
Note that I am using jQuery and the javascript is wrapped in the document ready.

First, you can't interact with the ws object till it establishes a connection to the server.
There are a couple of ways to handle this scenario. You can use the "onOpen" attribute and have it call a function once the web socket connect has been established.
However, you are probably better off just using the "onMessage" attribute and create a generic listener function that processes all web socket messages from the server.
function messageHandler(msg) {
if (msg.type == 'response' && msg.reqType == 'welcome'){
alert('user connected');
}
}

Related

How to send chat messages using converse library

I am using openfire as an XMPP server and using converse as client library. I want to send a chat message from my chat window to openfire. For this I want to send the text to a converse method which will send the message to the XMPP server.
I am trying to send the message using the following:
var msg = converse.env.$msg({
from: 'a1#localhost',
to: 'a6#localhost',
type: 'chat',
body: "Hi"
});
converse.send(msg);
But this sends the following frame in network of console in websocket:
message from='a1#localhost' to='a6#localhost' type='chat' body='Hi' xmlns='jabber:client'/>
This does not transfer message to the other user neither it stores it in the table. I am pretty much sure I am calling a wrong function. Can anyone povide any help.
You are calling the right function.
What you'll probably miss:
Listener of messages in "a6#localhost" client: as I read in documentation there are few functions
Probably, the right name of server. "localhost" has problem. You can
check Openfire for real service name on his own web panel
To check if a message it's delivered in Openfire you'll can check
OF's log (check debug one, but probably you'll have to enable it).
Real time messages are not stored on database, only groupchat's ones
and not everytime AND offline messages. To not find them on db means nothing
https://conversejs.org/docs/html/development.html
converse.chats.open('buddy#example.com');
converse.chats.get('buddy#example.com');
converse.listen.on('message', function (event, messageXML) { ... });
The syntax is wrong. conversejs uses strophe plugin to construct and send messages. It exposes the strophe $msg message builder for constructing stanzas. It has to be in the following format:
converse.env.$msg({from: 'a1#localhost', to: 'a6#localhost', type: 'chat'}).c('body').t('Hi');
You need to add a body node and within it a text node for the message.
You can also create and add your own api method and internally create a method that sends your custom stanza, and expose it using the api.

How do I send a channel message using channel.trigger with websocket-rails gem

I'm building a simple real-time chat app to learn how to use websockets with RoR and I don't think I'm understanding how channels work because they're not doing what I expect. I can successfully send a message to my Rails app using the dispatcher.trigger() method, and use my websocket controller to broadcast a message to all clients that subscribe to the channel. That all works fine. What does NOT work is using a channel (via the channel.trigger() method) to send a message to other clients. The websocket-rails wiki says...
Channel events currently happen outside of the Event Router flow. They
are meant for broadcasting events to a group of connected clients
simultaneously. If you wish to handle events with actions on the
server, trigger the event on the main dispatcher and specify which
controller action should handle it using the Event Router.
If I understand this correctly, I should be able to user the channel.trigger() method to broadcast a message to clients connected to the channel, without the message being routed through my RoR app, but it should still reach the other connected clients. So here's my code...
var dispatcher = new WebSocketRails('localhost:3000/websocket');
var channel = dispatcher.subscribe('channel_name');
channel.bind('channel_message', function(data) {
alert(data.message);
});
$("#send_message_button").click(function() {
obj = {message: "test"};
channel.trigger('channel_message', obj);
});
With the code listed above, I would expect that when I click the button, it sends a channel message using channel.trigger() and the channel_message binding should be executed on all clients, displaying an alert that reads "test". That doesn't happen. I'm using Chrome tools to inspect the websocket traffic and it shows the message being sent...
["channel_message",{"id":113458,"channel":'channel_name',"data":{"message":"test"},"token":"96fd4f51-6321-4309-941f-38110635f86f"}]
...but no message is received. My questions are...
Am I misunderstanding how channel-based websockets work with the websocket-rails gem?
If not, what am I doing wrong?
Thanks in advance for all your wisdom!
I was able to reproduce a working copy based on an off-the-shelf solution from the wiki along with your very own code.
I've packaged the whole thing here. The files you might be interested are home_controller.rb, application.js and home/index.html.erb.
It seems your understanding of channel-based websockets is correct. About the code, make sure to load the websocket javascript files and to enclose your code inside a document.ready. I had the exact same problem you're having without the latter.
//= require websocket_rails/main
$(function() {
// your code here...
});
Let me know if it works. Best Luck!

Establishing WebSocket Connection within and for a JS API

Aim: In order to provide a simple, easy-to-use JS library that communicates with a server I am trying to establish a WebSocket connection at the start of my API and define the library's functionality thereafter.
Problem: The issue is that my socket's readystate does not transition to 1 (ready) before the library is loaded and the user's script is run. Debugging this has confirmed this and I'm not sure how to ensure my WebSocket is established before proceeding with the user's script.
What I have:
(function(myObject) {
var socket = new WebSocket(url);
socket.emit = function() {
//do some tasks and create a var "message"
socket.send(message);
}
window.myObject = myObject.prototype = {
doSomething: function() {
socket.emit();
}
}
}(myObject = window.myObject || {}));
Above, I've defined a custom method (socket.emit()) on the socket object that, in turn, calls socket.send(). I do this to manipulate some data before sending it via socket.send(), reusing code that would otherwise be repeated.
Then I have some very basic html that includes this JS library and a simple script runs as follows:
$(document).ready(function() {
myObject.doSomething();
});
The error I get is: "Failed to execute 'send' on 'Websocket': already in CONNECTING state."
The library successfully loads but the Websocket does not complete connection before the client script is run. How can I ensure my WebSocket is connected (readystate == 1) before the API finishes loading?
Thanks for the help!
What you could do is buffer all messages in socket.emit as long as the socket is not connected and send them once you receive the onOpen callback.
While this will handle your current problem you will see that new ones will arise:
You might want to handle disconnects from your server and reconnects and therefore you might need to extend your library API anyhow to also expose connectionstate change events and force the library user to only send messages when connected.

How to handle socketIO when app is not running

I've been doing alot of testing with socketIO and have got stuck with handling situations where my node app is simply offline. The documentation provides no real insight into this issue.
So if i run my website and node app is simply not running, console.log gives:
GET http://[url]:[port]/socket.io/socket.io.js
Uncaught ReferenceError: io is not defined
This is hardly surprising, how ever what i don't understand is how to handle these errors and simply have the script try to attempt a reconnect until it finally does reconnect (if ever).
My script looks like this:
<script src="http://[url]:[port]/socket.io/socket.io.js"></script>
<script>
windows.onload = function()
{
socketio = io.connect("http://[url]:[port]");
socketio.on('connecting', function() {
console.log('trying to connect');
});
socketio.on('connect', function() {
console.log('connected');
});
}
</script>
Is there a way to handle this kind of problem ?
When the server is offline, your initial <script> tag to load the Socket.io client library fails, so you never get the io object in the first place.
To retry, you can add a new <script> tag to load the same URL again and see if it succeeds.
Better yet, copy the socket.io client library to the server hosting your HTML, so that the script will always load. You can then simply handle connection errors from io.connect().
There are a few events that you can bind to.
socket.on("connect_failed", function() {
// Do whatever you wanted to do on failure
});
For a full list of exposed events check here: exposed socket.io events
Edit
Ah, I'm sorry. I misunderstood your question. I thought you wanted to handle when the socket server was offline. If you want to handle not being able to get at the socket.io client script, maybe you could check if socket is null or undefined and handle thought that. Then also fire a setTimeout function to try and load the script asynchronously after a wait period and then check if socket is still undefined or null. Or, as the other answer suggests, pack the socket.io client library with the rest of your HTML page.

nodejs socket io cannot call emit of undefined. Causes?

I am using nodejs and socket io. The underlying purpose for the code is to ask for data from the server and to post it on the client website.
I have it made so that every 10 seconds, data is requested from the client to the server, and when the data is received, it shows up on the website.
The problem is that most of the time, receiving data from the server and getting it to the client works, but once in a while, it shuts off and throws an error that says that the socket method emit is undefined. I believe this means that the client is no longer defined.
server code:
sockets[to].emit('cm0101', {soCase : '2', soData : ret } );
this is the code that's getting the TypeError: cannot call method 'emit' of undefined.
What I am confused about is, it works 9 out 10 times, but it fails once in a while (presumably when the client is shut down for whatever reason. But there is no reason/identified cases of the client shutting down)
Did anyone else have the same problem? Does anyone know why this happens? Knowing all possible reasons for this error will help me a lot in trying to find out why this happens.
I assume you did not check sockets[to] before.
You should write your code like this:
var socketTo = sockets[to];
if ( socketTo ) {
sockets[to].emit('cm0101', {soCase : '2', soData : ret } );
}

Categories

Resources