My goal is to update the web page with some file. When I edit and save the file, and instantly its content appears updated to a page.
I´m using socket.io to handle this issue. But. I need some modifications on my code to approaches it.
:: My server side code:
var PORT = 8001;
var io = require("socket.io").listen(PORT);
var fs = require("fs");
io.sockets.on('connection', function(socket) {
console.log("Connected!");
socket.emit('connected', { accept: true});
console.log("Trying to send a content file to client...");
fs.readFile("file.txt","UTF-8", function(err, data) {
if (err) throw err;
socket.emit("requestFile", data );
console.log("Conteúdo:", data);
})
});
console.log("Application has started! Port: " + PORT);
:: My page
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" src="http://localhost:8001/socket.io/socket.io.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
.arquivo {
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
width: 900px;
border: 2px solid black;
-moz-border-radius: 3px;
}
</style>
<script type="text/javascript">
console.log("Try to logon...");
var socket = io.connect("localhost", {"port" : "8001"});
socket.on("connected", function(data) {
console.log("Connected User?", data.accept);
});
//recebe o arquivo indefinidamente
var requestFile = socket.on("requestFile", function(data) {
$("#arquivoSaida").html(data + "<br/>");
console.log(data);
});
setInterval(requestFile, 200);
</script>
</head>
<body>
<h3 style="font: Arial, Verdana; font-size: 14px; font-weight: bold;">
File updated:
</h3>
<div id="arquivoSaida">
</div>
</body>
</html>
I have used a setInterval to fires at 200 ms to request a file to a server. Any cue will be very welcome.
Thanks in advance!
-- UPDATED with Solution:
:: I did some alterations from my original code. This solution was provided by PuerkitoBio. Thanks, man!
The code updated:
var PORT = 8001;
var io = require("socket.io").listen(PORT);
var fs = require("fs");
io.sockets.on('connection', function(socket) {
console.log("Connected!");
socket.emit('connected', { accept: true});
console.log("Trying to send the content to a client...");
console.log("dir", __dirname);
fs.watch(__dirname + "/arquivo.txt", function(event, filename) {
console.log("Event:", event);
if (event == "change") {
fs.readFile("arquivo.txt","UTF-8", function(err, data) {
if (err) throw err;
socket.emit("receiveFile", data );
console.log("Content:", data);
})
}
});
});
console.log("Application has started! Port: " + PORT);
You can use fs.watchFile() and compare curr.mtime with prev.mtime to detect if the file has been modified. Then use readFile to send the content to your connected client. From the docs.
With sockets, you don't poll the data from the client, it gets pushed from the server when required (when your file changes, in your case). So you don't need the setInterval from the client side (you will watch for changes server-side using fs.watchFile, and push the content to your client, so your "requestFile" handler on the client will get called automatically (should be renamed receiveFile or something to be more accurate!).
Related
I have a Node.js application running on Heroku that calls an external website periodically.
This is roughly how we are calling the API using https:
https.get(options, res => {
let data = [];
res.on('data', chunk => {
data.push(chunk);
});
res.on('end', () => {
try{
var results = JSON.parse(Buffer.concat(data).toString());
//handle results normally.
}catch(e){
//error parsing response into a JSON. the reason is because Heroku returned a HTML error page
console.log('callOpenSeaAPI try catch error, original response: ', Buffer.concat(data).toString());
callback(e, null)
}
callback(null, results)
});
}).on('error', err => {
callback(err, null)
});
}
Out of 7000 times call, we will randomly get about 10 errors. The error will happen because the response is a html page instead of a JSON, that triggered the try catch error handler.
This is the HTML error page returned in the API response:
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8">
<title>SSL certificate error</title>
<style media="screen">
html,body,iframe {
margin: 0;
padding: 0;
}
html,body {
height: 100%;
overflow: hidden;
}
iframe {
width: 100%;
height: 100%;
border: 0;
}
</style>
</head>
<body>
<iframe src="//www.herokucdn.com/error-pages/ssl-cert-error.html"></iframe>
<script ...></script>
</body>
</html>
Do take note that this error page is returned by Heroku, not from the 3rd party api server.
Why is this happening?
I recently tried to run a nodejs chat demo and test it. It worked on the same computer as the program were running on, but the chat couldn't be reached from outside. This is the code for the server:
var WebSocketServer = require('ws').Server
var wss = new WebSocketServer({host: 'put_my_ip_in_here',port: 8000});
wss.on('connection', function(ws)
{
console.log('client connected...');
ws.on('message', function(message)
{
console.log('received from client: ' + message);
ws.send('received from server: ' + message);
});
});
I unblocked the port 8000 (udp and tcp as in my router and my firewall and told someone from outside my network to open the following page
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function()
{
function connect()
{
var socket = new WebSocket("ws://put_my_ip_in_here:8000");
socket.onopen = function() { message('Socket Status: '+socket.readyState+' (open)'); }
socket.onmessage= function(msg) { message('received: '+msg.data); }
function send()
{
var text = $('#text').val();
socket.send(text);
message('sent : '+text)
$('#text').val("");
}
{
$('#Log').append(msg+'</br>');
}
$('#text').keypress(function(event)
{
if (event.keyCode == '13')
{
send();
}
});
}
connect();
});
</script>
</head>
<body>
<div id="container">
<div id="Log"></div>
Input: <input id="text" type="text" />
</div>
</body>
</html>
But my computer/the chat wasnt reachable :c
Where is the problem? The demos seems to be running fine!
I try to make a chat with node.js and socket.io but I tried since 6 hours to resolve my problem but I don't succeed.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Socket.io</title>
</head>
<body>
<h1>Communication avec socket.io !</h1>
<div id="formulaire">
<form action="" method="post" id="form">
<input type="text" id="pseudo" placeholder="Pseudo"/>
<input type="text" id="message" placeholder="Message"/>
<input type="submit" value="Envoi"/>
</form>
</div>
<div id="wrapper">
Texte par défaut
</div>
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
var socket = io.connect('http://localhost:8080');
$("#formulaire").submit(function() {
var pseudo = $("#pseudo").val();
var message = $("#message").val();
alert(pseudo = " " + message);
socket.emit("pseudo", pseudo);
socket.emit("message", message);
});
socket.on("message", function (message) {
alert("bien récupéré depuis serveur: " + message); //It works
var wrapper = document.getElementById('wrapper');
wrapper.innerHTML = "Le message est: " + message; //It doesn't work ?????
});
</script>
</body>
</html>
app.js
var http = require("http");
var fs = require("fs");
// Serving index.html to the client
var server = http.createServer(function(req, res) {
fs.readFile("./index.html", "utf-8", function(error, content) {
res.writeHead(200, {"Content-Type": "text/html"});
res.end(content);
});
});
// Loading socket.io
var io = require("socket.io").listen(server);
// Logging in console when a client connects
io.sockets.on("connection", function (socket) {
//socket.emit("message", "A new client has connected");
socket.on("pseudo", function(pseudo) {
console.log(pseudo);
socket.emit("pseudo", pseudo);
});
socket.on("message", function(message) {
console.log(message);
socket.emit("message", message);
});
});
server.listen(8080);
I don't understand because the alert gets opened with the variable from the server message but innerHTML doesn't get filled.
Because pseudo and message are input fields in a form, by default, the page get's reloaded because you click a submit button. To prevent this, you need to put return false; at the end of the submit handler, like this:
$("#formulaire").submit(function() {
var pseudo = $("#pseudo").val();
var message = $("#message").val();
console.log(pseudo = " " + message);
socket.emit("pseudo", pseudo);
socket.emit("message", message);
return false;
});
Note that I replaced alert with console.log, of which the output can be viewed in the console, which you can open with F12 in Google Chrome. I find it to be less annoying for debugging purposes. (it doesn't create a popup and it can print arrays and objects)
My browser will ring, but Im unable to accept or reject the call. The accept and reject buttons do not show when I receive an incoming call. Am I missing something in my code? Need help!
my snippet is:
<!DOCTYPE html>
<html>
<head>
<title> Screenpop </title>
<script type="text/javascript"
src="//static.twilio.com/libs/twiliojs/1.2/twilio.min.js"></script>
<script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js">
</script>
<link rel="stylesheet"
href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css"/>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<head>
<link href="/images/stylesheets/favicon.ico"
type="image/x-icon" rel="icon" />
<link href="/stylesheets/playusclient.css"
type="text/css" rel="stylesheet" />
<script type="text/javascript">
var socket = io.connect();
$(function() {
$(".call").on("click", function() {
// The properties of this object will be sent as POST
// Parameters to URL which generates TwiML.
Twilio.Device.connect({
CallerId:'<%= phone_number %>' ,
// Replace this value with a verified Twilio number:
// https://www.twilio.com/user/account/phone-numbers/verified
PhoneNumber:$("#number").val() //pass in the value of the text field
});
});
$(".hangup").on("click", function() {
Twilio.Device.disconnectAll();
});
/* Create the Client with a Capability Token */
Twilio.Device.setup('<%= token %>', {debug: true});
/* Let us know when the client is ready. */
Twilio.Device.ready(function (device) {
$("#log").text("Ready");
});
Twilio.Device.incoming(function(connection) {
$( "#dialog-confirm" ).dialog({
resizable: false,
modal: true,
autoOpen: false,
buttons: {
"Accept": function() {
connection.accept();
$("#log").html("Call answered!");
$( this ).dialog( "close" );
},
"Reject": function() {
connection.reject();
$("#log").html("Call rejected! Awaiting next call.");
$( this ).dialog( "close" );
}
}
});
$("#log").html("Incoming call from " + connection.parameters.From);
socket.emit("incoming",connection.parameters.From);
});
Twilio.Device.disconnect(function(connection) {
$("#log").html("Ready");
});
/* Report any errors on the screen */
Twilio.Device.error(function (error) {
$("#log").text("Error: " + error.message);
});
Twilio.Device.connect(function (conn) {
$("#log").text("Successfully established call");
});
socket.on('foundPerson', function(data) {
$("#dialog-confirm").html("<i>" + data.number + "
</i><br /><b>" + data.name + "</b><img src='" +
data.photo + "' />");
$( "#dialog-confirm" ).dialog( "open" );
});
});
</script>
</head>
<body>
<div id="dialog-confirm" title="Receive Call?" style="display: none">
</div>
<button class="call">
Call
</button>
<button class="hangup">
Hangup
</button>
<input id="number" type="text" placeholder="Enter a number like
+16519998888"/>
<div id="log">Loading pigeons...</div>
</body>
</html>
Twilio developer evangelist here.
I think you may be opening your JQuery UI dialog incorrectly here.
What you want to do is set up the dialog outside of the incoming call event and then, when you get the call event, open the dialog.
So, it should be a bit more like this:
<script type="text/javascript">
var socket = io.connect();
// set up the dialog
$(function() {
var dialog = $("#dialog-confirm").dialog({
resizable: false,
modal: true,
autoOpen: false,
buttons: {
"Accept": function() {
Twilio.Device.activeConnection().accept();
$("#log").html("Call answered!");
$( this ).dialog( "close" );
},
"Reject": function() {
Twilio.Device.activeConnection().reject();
$("#log").html("Call rejected! Awaiting next call.");
$( this ).dialog( "close" );
}
}
});
// do other Twilio.Device setup here
Twilio.Device.incoming(function(connection) {
// open the dialog
dialog.dialog("open");
$("#log").html("Incoming call from " + connection.parameters.From);
socket.emit("incoming",connection.parameters.From);
});
// do other Twilio.Device setup here
</script>
Let me know if that helps at all!
I am messing around with socket.io and node.js, and was wondering how to accomplish the following: I have a simple form that sends a text string to the server, and the server sends it back, and it gets appended to a div. what I would like to do is have that div update for all users in all browsers, currently it only updates the one that the message was sent from.
code from app.js (node.js server) :
io.sockets.on('connection', function(socket) {
socket.on('send_message', function(data) {
data.message = data.message + ' yo<br/>';
socket.emit('get_message',data);
});
});
code on client-side:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
$(document).ready(function() {
var socket = io.connect('http://localhost:3000');
$('#sender').live('click',function() {
var user_message = $('#message_box').val()
socket.emit('send_message',{message: user_message});
});
socket.on('get_message', function(data) {
$('#data').append(data.message);
});
});
</script>
and the html:
<div id='data'></div>
<input type='text' id='message_box' placeholder='send message'>
<button id='sender'>Send Message</button>
what should I be doing to send messages to multiple browsers?
Change
socket.emit('get_message',data);
To
socket.broadcast.emit('get_message',data);
To broadcast it to all connected users, except to the socket where you are calling the broadcast on.
If you also want to include that socket you can do
io.sockets.emit('get_message', data);