I'm starting with Node.js and I have already a problem in my first program. Below is the code I'm using. Index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Random Temperatures</title>
</head>
<body>
<input type="text" id="tb" name="tb" />
<input type="button" value="Random Number!" id="myButton" name="myButton"/>
<script src="client.js"></script>
</body>
</html>
Client.js:
const textBox = document.getElementById('tb');
const button = document.getElementById('myButton');
button.addEventListener('click', function(e) {
var rnd = Math.floor(Math.random() * 100);
textBox.value = rnd;
});
Server.js:
var app = require('http').createServer(response);
var fs = require('fs');
app.listen(8080);
console.log("App running…");
function response(req, res) {
fs.readFile(__dirname + '/public/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Failed to load file index.html');
}
res.writeHead(200);
res.end(data);
});
}
When I start the application I go to the browser the text box and the button appear. But in the browser console I'm getting these errors:
client.js:1 Uncaught SyntaxError: Unexpected token <
ContentScript.js:112 Exception in onResRdy: TypeError: Cannot read
property 'htmlRes' of undefined
localhost/:1 Unchecked runtime.lastError: Could not establish
connection. Receiving end does not exist.
I guess my problem is the linking between the 3 files but I tried several things and I can't solve the problem. I'm sure it's a stupid error but forgive me I'm just getting start. Any advice?
The browser (because you have <script src="/client.js">) makes a request for /client.js
The server:
Gets the request
Runs response
Reads index.html
Sends it to the browser
Since index.html starts with <, the browser throws an error when it tries to run it as JavaScript.
Why are you giving the browser index.html when it asks for client.js?
You need to examine the request object, determine what URL is being asked for, write logic to return the correct resource with the correct status code and the correct content-type, and then return that to the client.
The Node.js documentation has an example of this but you should probably stop trying to use createServer directly — since it involves a massive amount of wheel reinvention — switch to using Express and work through the (very short) getting started guide which includes a section on using the static module to serve up static files.
Related
I am working on a program that relies heavily on web workers. But I am unable to get them to function as required. This is just a minified example but the format is more or less similar.
I have 4 files:
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello World!</title>
</head>
<body>
<button id="btn">GO</button>
<script src="./index.js" type="module"></script>
</body>
</html>
index.js
const worker = new Worker("./worker.js", {type: "module"})
worker.addEventListener("message", async ({ data }) => {
console.log(data);
});
worker.onerror = function (event) {
throw new Error(event.message + " (" + event.filename + ":" + event.lineno + ")");
}
window.sendMessage = function (args) {
worker.postMessage(args);
};
async function onclick() {
sendMessage("World")
}
document.getElementById("btn").addEventListener("click", onclick, false);
worker.js
import * as p from "hello.js"
console.log("Worker Started")
onmessage = function (e) {
p.greet(e.data)
}
hello.js
export function greet(who){
alert("Hello " + who)
}
The worker should output "Worker Started".
When the button is clicked, the UI thread will send a message to the worker which will then call the greet function.
However the worker immediately errors and returns a value via worker.onerror
The value it returns in Chromium(and Chromium based) is undefined
Uncaught Error: undefined (undefined:undefined)
at Worker.worker.onerror (index.js:8:11)
I have tested this across various browsers on 2 computers with 3 different operating systems with no success.
From what I understand. Firefox does not support this the way I am doing it.
Uncaught Error: SyntaxError: import declarations may only appear at top level of a module (http://localhost:8000/worker.js:1)
I have taken a look at this answer here
https://stackoverflow.com/a/33432215/19140286
however It does not let me import a file into my worker function.
Running chrome with
chromium --allow-file-access-from-files
does not solve the issue
examples are run with a local server via
python -m http.server
Here is a repository with the files
https://github.com/KivalM/web-workers
Such an error on a Worker without a .message, .filename, or .lineno points toward a network error, if it was a script error you'd get these filled.
Maybe your worker URL is also invalid, but at least your module one is.
If you don't use module maps, you must prepend ./ to relative import URLs.
import * as p from "./hello.js"
Once this is fixed, you'll face a new error, a script error this time:
alert() is only accessible in Window contexts. You can't call this method from a Worker. You should anyway avoid its use even in Window contexts because its influence on the JS environment is far from being obvious and usually isn't as useful in debugging as the Console API.
I'm starting with Node.js and I have already a problem in my first program. Below is the code I'm using. Index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Random Temperatures</title>
</head>
<body>
<input type="text" id="tb" name="tb" />
<input type="button" value="Random Number!" id="myButton" name="myButton"/>
<script src="client.js"></script>
</body>
</html>
Client.js:
const textBox = document.getElementById('tb');
const button = document.getElementById('myButton');
button.addEventListener('click', function(e) {
var rnd = Math.floor(Math.random() * 100);
textBox.value = rnd;
});
Server.js:
var app = require('http').createServer(response);
var fs = require('fs');
app.listen(8080);
console.log("App running…");
function response(req, res) {
fs.readFile(__dirname + '/public/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Failed to load file index.html');
}
res.writeHead(200);
res.end(data);
});
}
When I start the application I go to the browser the text box and the button appear. But in the browser console I'm getting these errors:
client.js:1 Uncaught SyntaxError: Unexpected token <
ContentScript.js:112 Exception in onResRdy: TypeError: Cannot read
property 'htmlRes' of undefined
localhost/:1 Unchecked runtime.lastError: Could not establish
connection. Receiving end does not exist.
I guess my problem is the linking between the 3 files but I tried several things and I can't solve the problem. I'm sure it's a stupid error but forgive me I'm just getting start. Any advice?
The browser (because you have <script src="/client.js">) makes a request for /client.js
The server:
Gets the request
Runs response
Reads index.html
Sends it to the browser
Since index.html starts with <, the browser throws an error when it tries to run it as JavaScript.
Why are you giving the browser index.html when it asks for client.js?
You need to examine the request object, determine what URL is being asked for, write logic to return the correct resource with the correct status code and the correct content-type, and then return that to the client.
The Node.js documentation has an example of this but you should probably stop trying to use createServer directly — since it involves a massive amount of wheel reinvention — switch to using Express and work through the (very short) getting started guide which includes a section on using the static module to serve up static files.
I'm starting with Node.js and I have already a problem in my first program. Below is the code I'm using. Index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Random Temperatures</title>
</head>
<body>
<input type="text" id="tb" name="tb" />
<input type="button" value="Random Number!" id="myButton" name="myButton"/>
<script src="client.js"></script>
</body>
</html>
Client.js:
const textBox = document.getElementById('tb');
const button = document.getElementById('myButton');
button.addEventListener('click', function(e) {
var rnd = Math.floor(Math.random() * 100);
textBox.value = rnd;
});
Server.js:
var app = require('http').createServer(response);
var fs = require('fs');
app.listen(8080);
console.log("App running…");
function response(req, res) {
fs.readFile(__dirname + '/public/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Failed to load file index.html');
}
res.writeHead(200);
res.end(data);
});
}
When I start the application I go to the browser the text box and the button appear. But in the browser console I'm getting these errors:
client.js:1 Uncaught SyntaxError: Unexpected token <
ContentScript.js:112 Exception in onResRdy: TypeError: Cannot read
property 'htmlRes' of undefined
localhost/:1 Unchecked runtime.lastError: Could not establish
connection. Receiving end does not exist.
I guess my problem is the linking between the 3 files but I tried several things and I can't solve the problem. I'm sure it's a stupid error but forgive me I'm just getting start. Any advice?
The browser (because you have <script src="/client.js">) makes a request for /client.js
The server:
Gets the request
Runs response
Reads index.html
Sends it to the browser
Since index.html starts with <, the browser throws an error when it tries to run it as JavaScript.
Why are you giving the browser index.html when it asks for client.js?
You need to examine the request object, determine what URL is being asked for, write logic to return the correct resource with the correct status code and the correct content-type, and then return that to the client.
The Node.js documentation has an example of this but you should probably stop trying to use createServer directly — since it involves a massive amount of wheel reinvention — switch to using Express and work through the (very short) getting started guide which includes a section on using the static module to serve up static files.
I am new to Node.js and javascript, hence don't have much experience and in need of some help.
I have a script that opens a simple server socket and just listens to incoming connection and prints the incoming message to the screen:
var net = require('net');
var server = net.createServer();
server.on('connection', handleConnection);
server.listen(9000, function() {
console.log('server listening to %j', server.address());
});
function handleConnection(conn) {
var remoteAddress = conn.remoteAddress + ':' + conn.remotePort;
console.log('new client connection from %s', remoteAddress);
conn.on('data', onConnData);
conn.once('close', onConnClose);
conn.on('error', onConnError);
function onConnData(d) {
var chunks = [];
chunks.push(d);
console.log('Client at %s says %s', remoteAddress, Buffer.concat(chunks).toString());
conn.write(d);
}
function onConnClose() {
console.log('connection from %s closed', remoteAddress);
}
function onConnError(err) {
console.log('Connection %s error: %s', remoteAddress, err.message);
}
}
I have tested it and it works when i run it from the IDE (eclipse).
What I am trying to do is to incorporate this code inside an HTML file.
The HTML file does not suppose to be accessed from the out side, its for learning purposes only.
Basically i would like to open the HTML file, it should run the code in the background (listen to the socket) and once the is a connection and data coming in it should print it on the screen (sing alert for example).
The HTML code looks like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>some title</title>
</head>
<body>
<script
type = "text/javascript" src = "simple_server.js">
</script>
</body>
</html>
While trying to open the HTML file using a browser or inside eclipse it does nothing.
My question is, is it even possible? If it is, what am i doing wrong and how may I fix it?
Any help would be appreciated. Thank you.
I'm trying to create a webapp for a web art class using node (w/ npm) and express. The idea is to have the body of the site be all one color, but anyone can text the site a hexcode/CSS color at a Twilio number and the color of the site will instantly change to that color value.
Essentially how it works is the server receives a POST request from Twilio at http://example.com/message, which contains the body of the text message. It writes it to a temporary file at ~/app/.data/color.tmp, which is accessed by the client with a jQuery .get() call to http://example.com/color, which returns
So here's the problem: I got a version of the app working on glitch.me, so I know that this code can work, but I'm having a lot of trouble getting it to work on my domain. I installed the app and can start it with npm, and it successfully shows me the HTML page, but the Chrome devtools show the script is receiving a 403 when it tries to access /color. Also, new texts to my site aren't changing the color value in /.data/color.tmp. I thought it might be a permissions issue but I checked them and they seem fine.
Here's the server file and the script on the index.html page:
app/server.js
var express = require('express');
var bodyParser = require('body-parser');
var fs = require('fs');
var app = express();
app.use(bodyParser.urlencoded({extended: false}));
var dataPath = '.data/color.tmp';
// set a new color (saves posted color to disk)
app.post("/message", function (request, response) {
var dataStr = JSON.stringify(request.body.Body);
fs.writeFile(dataPath, dataStr);
response.end();
});
// get the saved color (reading from disk)
app.get("/color", function (request, response) {
var dataStr = fs.readFileSync(dataPath).toString();
response.send(JSON.parse(dataStr));
});
app.get("/", function (request, response) {
response.sendFile(__dirname + '/views/index.html');
});
var listener = app.listen(process.env.PORT, function () {
console.log('listening on port ' + listener.address().port);
});
app/views/index.html
<script>
// checks server for color value and sets background
function checkForColorChange() {
$.get('/color', function getColorComplete(data) {
document.body.style.backgroundColor = data;
console.log(data);
})
}
// Poll the server at 2000ms interval
setInterval(checkForColorChange, 2000);
checkForColorChange();
</script>
Anyway, I feel like I must be missing something really obvious if it worked so easily on Glitch and won't on my website, but I've been stuck for a few days and am not making any progress! Any help would be so appreciated. Let me know if anything's unclear too.
(See update below for a working example)
TL;DR - example:
Original answer
There are few problems with your code:
you're not checking for errors
you're using blocking functions
you're implicitly relying on file permissions but you're not checking it
you're using string concatenation instead of path.join to join paths
you're constantly polling for new data instead of waiting for it to change
you're not catching exceptions of functions that can raise exception
you're not waiting for async operations to finish and you don't handle errors
The main problem that you're experiencing right now is most likely with the file permissions. The good news is that you don't need any file access for what you're doing and using files for that is not optimal anyway. All you need is to store the color in a variable if you don't need it it persist between server restarts - and even if you do then I would use a simple database for that.
For example:
// some initial value:
var color = '#ffffff';
app.post("/message", function (request, response) {
var color = request.body.Body;
response.end();
});
// get the saved color (reading from disk)
app.get("/color", function (request, response) {
response.send(color);
});
app.get("/", function (request, response) {
response.sendFile(__dirname + '/views/index.html');
});
var listener = app.listen(process.env.PORT, function () {
console.log('listening on port ' + listener.address().port);
});
This is the first change that I would use - don't rely on the file system, permissions, race conditions etc.
Another problem that you had with your code was using blocking functions inside of request handlers. You should never use any blocking function (those with "Sync" in their name) except the first tick of the event loop.
Another improvement that I would make would be using WebSocket or Socket.io instead of polling for data on regular intervals. This would be quite easy to code. See this answer for examples:
Differences between socket.io and websockets
A plus of doing that would be that all of your students would get the color changed instantly and at the same time instead of in random moments spanning 2 seconds.
Update
I wrote an example of what I was describing above.
The POST endpoint is slightly different - it uses /color route and color=#abcdef instead of /message and Body=... but you can easily change it if you want - see below.
Server code - server.js:
// requires removed for brevity
const app = express();
const server = http.Server(app);
const io = socket(server);
let color = '#ffffff';
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/', express.static(path.join(__dirname, 'html')));
io.on('connection', (s) => {
console.log('Socket.io client connected');
s.emit('color', color);
});
app.post('/color', (req, res) => {
color = req.body.color;
console.log('Changing color to', color);
io.emit('color', color);
res.send({ color });
});
server.listen(3338, () => console.log('Listening on 3338'));
HTML page - index.html:
<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<meta name=viewport content="width=device-width, initial-scale=1">
<title>Node Live Color</title>
<link href="/style.css" rel=stylesheet>
</head>
<body>
<h1>Node Live Color</h1>
<script src="/socket.io/socket.io.js"></script>
<script src="/script.js"></script>
</body>
</html>
Style sheet - style.css:
body {
transition: background-color 2s ease;
background-color: #fff;
}
Client-side JavaScript - script.js:
var s = io();
s.on('color', function (color) {
document.body.style.backgroundColor = color;
});
What is particularly interesting is how simple is the client side code.
For your original endpoint use this in server.js:
app.post('/message', (req, res) => {
color = req.body.Body;
console.log('Changing color to', color);
io.emit('color', color);
res.end();
});
Full example is available on GitHub:
https://github.com/rsp/node-live-color
I tested it locally and on Heroku. You can click this button to deploy it on Heroku and test yourself:
Enjoy.
I think, the problem is in var dataStr = fs.readFileSync(dataPath).toString();. Please change your dataPath as follow:
var dataPath = __dirname + '/data/color.tmp';
And also make sure that file has read/write permission by the .