I am new to node.js (just few days in) and am learning through a tutorial from youtube (don't know if it's allowed to post a link or not).
I am trying to create a database in couchDB. Everything works fine but as soon as I try to enter any details on the form, it displays the exception "Error creating Database Address" (Address is the name of the database I am trying to create)
I followed the tutorial very carefully and have been searching for a solution for a while now but end up with nothing.
Please help if you found something.
App.js:
var express = require('express');
var routes = require('./routes');
var http = require('http');
var path = require('path');
var urlencoded = require('url');
var bodyParser = require('body-parser');
var json = require('json');
var logger = require('logger');
var methodOverride = require('method-override');
var nano = require('nano')('http://admin:password#localhost:5984');
var db = nano.use('address');
var app = express();
app.set('port', process.env.PORT || 3000);
app.set('views',path.join(__dirname,'views'));
app.set('view engine', 'jade');
app.use(bodyParser.json());
// app.use(bodyParser.urlencoded());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(methodOverride());
app.use(express.static(path.join(__dirname, 'public')));
app.get('/',routes.index);
app.post('/createdb', function(req, res) {
nano.db.create(req.body.dbname, function(err){
if(err) {
res.send("Error creating Database " + req.body.dbname);
return;
}
res.send("Database " + req.body.dbname + "created successfully");
});
});
app.post('/new_contact', function(req, res) {
var name = req.body.name;
var phone = req.body.phone;
db.insert({name : name, phone : phone, crazy : true}, phone, function(err,body, header) {
if(err) {
res.send("Error creating contact");
return;
}
res.send("Contact created successfully");
});
});
app.post('/view_contact', function(req, res) {
var alldoc = "Following are the contacts";
db.get(req.body.phone, {revs_info : true}, function(err, body) {
if(!err) {
console.log(body);
}
if(body) {
alldoc += "Name: " + body.name + "<br/>Phone Number: " + body.phone;
}
else {
alldoc = "No records found";
}
res.send(alldoc);
});
});
app.post('/delete_contact', function(req, res) {
db.get(req.body.phone, {revs_info : true}, function(err, body) {
if(!err) {
db.destroy(req.body.phone, body._rev, function(err, body) {
if(err) {
res.send("error deleting contact");
}
});
res.send("Contacts deleted successfullly");
}
});
});
http.createServer(app).listen(app.get('port'), function() {
console.log('Express server listening on port: ' + app.get('port'));
});
index.js
exports.index = function(req,res) {
res.render('index', {title: 'express'});
};
createdb.js
exports.create = function(req, res) {
nano.db.create(req.body.dbname, function() {
if(err) {
res.send("Error creating the Database");
return;
}
res.send("database created successfully");
});
};
index.js and createdb.js both are in routes folder
index.jade
extend layout
block content
h1 Add new Contact
form(method="POST", action = '/new_contact')
p name:
input#title(type = "text", name = "name")
p Phone No.:
input#title(type = "text", name = "phone")
p: button(type = "submit") Add new Contact
h1 Add new Database
form(method = "POST", action= "/createdb")
p Database name:
input#title(type = "text", name = "dbname")
p: button(type="submit") Add new Database
h1 enter Phone number to delete new_contact
form(method = "POST", action= "/delete_contact")
p Phone No.:
input#title(type = "text", name = "phone")
p: button(type="submit") Delete Contact
h1 View Specific contact
form(method = "POST", action= "/view_contact")
p Phone No.:
input#title(type = "text", name = "phone")
p: button(type="submit") Search Contact
layout.jade
doctype html
html
head
title = title
//- link(rel='stylesheet', href='/stylesheet/style.css')
body
block content
layout.jade and index.jade are present in views folder
package.json
{
"name": "sample",
"version": "1.0.0",
"description": "just a sample.",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.19.0",
"errorhandler": "^1.5.1",
"express": "^4.17.1",
"express-session": "^1.17.1",
"jade": "^1.11.0",
"json": "^10.0.0",
"logger": "0.0.1",
"method-override": "^3.0.0",
"nano": "^9.0.3",
"pug": "^3.0.2",
"serve-favicon": "^2.5.0",
"url": "^0.11.0"
}
}
Just briefly skimming over the code, it looks like you're not passing any authentication details to nano:
var nano = require('nano')('http://localhost:5984');
var db = nano.use('address');
/* ... */
app.post('/createdb', function(req, res) {
nano.db.create(req.body.dbname, function(err){
This might have worked in old versions of CouchDB running in admin party mode, which is not supported anymore from CouchDB 3.0 onwards.
When installing CouchDB locally, you'll need to setup a admin user and password before getting started.
When using nano, you need to provide the credentials like:
var nano = require('nano')('http://admin:password#localhost:5984')
Related
I'm getting this cannot GET error whenever I run my app on a live server with VS Code. My best guess is that it has to do with my routing being incorrect, I'm just not sure what about my routing is wrong. Any sort of help is appreciated <3
The goal is to send a POST request with the user's email inputted into a form element when the app is finished.
app.js
const express = require('express');
const request = require('request');
const bodyParser = require('body-parser');
const path = require('path');
const app = express();
//Middleware
app.use(express.json());
app.use(bodyParser.urlencoded({extended: false}));
console.log("The directory is:", (path.join(__dirname, '/site')));
app.use(express.static(path.join(__dirname, '/site')));
app.post('/', (req, res) => {
console.log('hey!');
});
app.listen(5000, console.log('Server started!'))
landing.html
<form action="/subscribe" method="POST">
<div class="newsletter-form-grp">
<i class="far fa-envelope"></i>
<input name="email" id="email" required pattern="[a-z0-9.%+-]+#[a-z0-9.-]+\.[a-z]{2,4}$" type="email" placeholder="Enter your email...">
</div>
<button id="cta">SUBSCRIBE <i class="fas fa-paper-plane"></i></button>
</form>
JS Code inside landing.html
<script>
//form submission
let cta = document.getElementById('cta');
let email = document.getElementById('email').value;
let status = document.getElementById('status');
cta.addEventListener('click', (event) => {
event.preventDefault();
if(this.email.value == null || this.email.value == "") {
status.classList.add('statusShow');
} else {
let fetchData = {
method: 'POST',
body: JSON.stringify({email: this.email.value, js: true}),
headers: {"Content-Type": "application/json"}
}
fetch('/subscribe', fetchData)
.then(res => {
if(res.ok) {
// yay
} else {
status.classList.add('statusShow');
}
})
}
});
</script>
JSON Package
{
"name": "Main",
"version": "1.0.0",
"description": "",
"main": "site/js/app.js",
"dependencies": {
"body-parser": "^1.19.0",
"express": "^4.17.1",
"index": "^0.4.0",
"request": "^2.88.2"
},
"devDependencies": {
"nodemon": "^2.0.15"
},
"scripts": {
"serve": "node app",
"dev": "nodemon app"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Project Tree: https://imgur.com/a/B9Ucrap
Your landing.html is a static file (in the site folder?), and you also do not have a GET route defined in Express to serve this page. So, in order to access it from your browser, you need to use: http://localhost:5000/landing.html.
Your form says: <form action='/subscribe' action='POST'>. Therefore, your Express needs this route defined:
app.post("/subscribe", (req, res) => {
console.log("hey!");
res.send("got it!");
});
BTW, your Html doesn't have an element with id of status. Your subscribe button click event code will hit an error.
I am trying to dynamically populate the WORD Document using npm docx. I am trying to read the data from the SQLite database but due to async node js property the values are not getting into the variable and it shows undefined. If I make the function synchronous the npm docx throws error and doesn't populate the document.
package.json
{
"name": "demoName",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.19.0",
"docx": "^5.1.1",
"express": "^4.17.1",
"md5": "^2.2.1",
"sqlite3": "^4.2.0"
}
}
index.js
const docx = require('docx');
var express = require('express');
var app = express();
var db = require("./database.js")
var bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
const { AlignmentType, Document, Footer, Header, HeadingLevel, Packer, Paragraph, TextRun, UnderlineType, Table, TableCell, TableRow } = docx;
app.get("/doc", async(req, res) => {
var sql = "select * from DocDetails"
var params = []
//let DocDetailsData;
//let DocDetailsData = [{docId: "Some Doc Id"}];
const DocDetailsData = db.all(sql, params, (err, rows) => {
if (err) {
res.status(400).json({"error":err.message});
return;
}
console.log(rows[0]);
return rows[0];
});
console.log(DocDetailsData.docId);
const doc = new Document();
doc.addSection({
children: [
new Paragraph({
children: [
new TextRun({
text: "DEMO TEST DOCUMENT"
}),
new TextRun({
text: DocDetailsData.docId,
}),
]
}),
],
});
const b64string = await Packer.toBase64String(doc);
res.setHeader('Content-Disposition', 'attachment; filename=My Document.docx');
res.send(Buffer.from(b64string, 'base64'));
});
madeDoc = function(){
}
app.use(function(req, res){
res.status(404);
});
var server = app.listen(4041, function () {
var host = 'localhost'
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
database.js
var sqlite3 = require('sqlite3').verbose()
var md5 = require('md5')
const DBSOURCE = "db.sqlite"
let db = new sqlite3.Database(DBSOURCE, (err) => {
if (err) {
// Cannot open database
console.error(err.message)
throw err
}else{
console.log('Connected to the SQLite database.')
db.run(`CREATE TABLE DocDetails (
id INTEGER PRIMARY KEY,
docId text NOT NULL,
version float NULL,
editedBy text NULL,
editedDate text NULL,
effectiveDate text NULL)`,
(err) => {
if (err) {
// Table already created
console.log('Table not created');
}else{
console.log('Table created');
var insert = 'INSERT INTO DocDetails (docId, version, editedBy, editedDate, effectiveDate) VALUES (?,?,?,?,?)'
db.run(insert, ["NESS-RD-TEMP-EDCHB",2.1, "manab", "18-Jul-2017", "18-Jul-2020"])
}
})
}
});
module.exports = db
If you go to localhost:4041/doc, a word document should get downloaded but it shows only one row and not the data from database. I need the database value to be populated in the doc.
Thanks.
In order for this example to work, you need to understand how to work with asynchronous execution and callbacks. You cannot return anything from the callback and get it in the DocDetailsData variable as it would in synchronous code, because when you call the db.all method, the code continues to execute further, without waiting for the callback that you passed to it to work. Instead, you need to put the code for generating the doc file in the callback and do it in it. I hope that at least I could explain to you how it works. This is how your code will work correctly:
index.js
const docx = require('docx');
var express = require('express');
var app = express();
var db = require("./database.js")
var bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
const { AlignmentType, Document, Footer, Header, HeadingLevel, Packer, Paragraph, TextRun, UnderlineType, Table, TableCell, TableRow } = docx;
app.get("/doc", async (req, res) => {
var sql = "select * from DocDetails"
var params = []
db.all(sql, params, async (err, rows) => {
if (err) {
res.status(400).json({"error":err.message});
return;
}
const DocDetailsData = rows[0];
const doc = new Document();
doc.addSection({
children: [
new Paragraph({
children: [
new TextRun({
text: "DEMO TEST DOCUMENT"
}),
new TextRun({
text: DocDetailsData.docId,
}),
]
}),
],
});
const b64string = await Packer.toBase64String(doc);
res.setHeader('Content-Disposition', 'attachment; filename=My Document.docx');
res.send(Buffer.from(b64string, 'base64'));
});
});
app.use(function(req, res){
res.status(404);
});
var server = app.listen(4041, function () {
var host = 'localhost'
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
});
database.js does not require changes
So im trying to deploy a simple twitter like app to HEROKU or MongoDB and i'm currently nailing either. For mongodb I get one out of two outcomes, either a internal server error or the actual code displaying on the browser instead of the app. Since I have two separate folders for each implementation i'm going to post subsequently.
MONGODB
Index.js (This is the server side node code)
const express = require('express');
//Cors permite que cualquiera se comunique con el server.
const cors = require('cors');
const monk = require('monk');
const Filter = require('bad-words');
const rateLimit = require('express-rate-limit');
const filter = new Filter();
const app = express();
const db = monk(process.env.MONGO_URI || 'localhost/meower');
const mews = db.get('mews');
//ORDER MATTERS, WHAT IS FIRST GETS EXECUTED FIRST
app.enable('trust proxy');
app.use(cors());
//any incoming request that is JSON will pass
app.use(express.json());
//server, when you get a request run this function.
app.get('/',(request,response) => {
res.json({
message: 'Meower!'
});
});
app.get('/mews', (req,res) => {
mews
.find()
.then(mews => {
res.json(mews);
});
});
function isvalidmew(mew){
return mew.name && mew.name.toString().trim() !== '' &&
mew.content && mew.content.toString().trim() !== '';
}
//limit the submit rate
app.use(rateLimit({
windowMs: 30 * 1000,
max: 2
}));
//this will wait for incoming data and insert in database
app.post('/mews', (req,res) => {
if(isvalidmew(req.body)){
const mew = {
name: filter.clean(req.body.name.toString()),
content: filter.clean(req.body.content.toString()),
created: new Date()
};
mews
.insert(mew)
.then(createdMew => {
res.json(createdMew);
});
} else {
res.status(422);
res.json({
message:'Hey! Name and Content are required!'
});
}
});
//abre el server en el puerto 5000
app.listen(5000, () => {
console.log('Listening on http://localhost:5000');
});
Client.js
const form = document.querySelector('form');
const loadingElement = document.querySelector('.loading');
const mewsElement = document.querySelector('.mews');
const API_URL = 'http://localhost:5000/mews';
loadingElement.style.display = '';
console.log('hola')
listallmews();
form.addEventListener('submit', (event) => {
event.preventDefault();
const formData = new FormData(form);
//We grab the stuff from the form
const name = formData.get('name');
const content = formData.get('content');
//We put it in an object
const mew = {
name,
content
};
//We send the data to the server
form.style.display = 'none';
loadingElement.style.display = '';
fetch(API_URL, {
method: 'POST',
body: JSON.stringify(mew),
headers : {
'content-type':'application/json'
}
}).then(response => response.json())
.then(createdMew => {
form.reset();
setTimeout(() => {
form.style.display = '';
},30000);
listallmews();
});
});
function listallmews(){
mewsElement.innerHTML = '';
fetch(API_URL)
.then(response => response.json())
.then(mews => {
console.log(mews);
mews.reverse();
mews.forEach(mew =>{
const div = document.createElement('div');
const header = document.createElement('h3');
header.textContent= mew.name
const contents = document.createElement('p')
contents.textContent= mew.content;
const date = document.createElement('small');
date.textContent = new Date(mew.created);
div.appendChild(header);
div.appendChild(contents);
div.appendChild(date);
mewsElement.appendChild(div);
});
loadingElement.style.display = 'none'
});
}
now.json
{
"name": "camitter-api",
"version": 2,
"builds": [
{
"src": "index.js",
"use": "#now/node-server"
}
],
"routes": [
{ "src": "/.*", "dest": "index.js" }
],
"env": {
"MONGO_URI": "#camitter-db"
}
}
and package.json
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js"
},
"keywords": [],
"author": "CJ R. <cj#null.computer> (https://w3cj.now.sh)",
"license": "MIT",
"dependencies": {
"bad-words": "^1.6.3",
"cors": "^2.8.4",
"express": "^4.16.3",
"express-rate-limit": "^3.1.1",
"monk": "^6.0.6",
"morgan": "^1.9.1"
},
"devDependencies": {
"nodemon": "^1.18.4"
}
}
And this is the terminal output on implementation. Currently the link shows "internal server error"
Alejandro#DESKTOP-LOJH5G7 MINGW64 ~/Desktop/Programacion/Meower
$ now secrets add camisite mongodb+srv://alenieto:myactualpassword#camisite-irtu2.mongodb.net/test?retryWrites=true&w=majority
[1] 444
Alejandro#DESKTOP-LOJH5G7 MINGW64 ~/Desktop/Programacion/Meower
$ Now CLI 18.0.0
Success! Secret camisite added under alenieto97 [709ms]
$ now -e MONGO_URI=#camisite
Now CLI 18.0.0
? Set up and deploy “~\Desktop\Programacion\Meower”? [Y/n] y
? Which scope do you want to deploy to? Alejandro Nieto
? Found project “alenieto97/meower”. Link to it? [Y/n] n
? Link to different existing project? [Y/n] n
? What’s your project’s name? camisite
? In which directory is your code located? ./
No framework detected. Default project settings:
- Build Command: `npm run now-build` or `npm run build`
- Output Directory: `public` if it exists, or `.`
� Inspect: https://zeit.co/alenieto97/camisite/ei55o9z4q [2s]
✅ Production: https://camisite.now.sh [copied to clipboard] [5s]
� Deployed to production. Run `now --prod` to overwrite later (https://zeit.ink/2F).
� To change the domain or build command, go to https://zeit.co/alenieto97/camisite/settings
[1]+ Done now secrets add camisite mongodb+srv://alenieto:lapata97#camisite-irtu2.mongodb.net/test?retryWrites=true
Alejandro#DESKTOP-LOJH5G7 MINGW64 ~/Desktop/Programacion/Meower
$ cd server
Alejandro#DESKTOP-LOJH5G7 MINGW64 ~/Desktop/Programacion/Meower/server
$ now -e MONGO_URI=#camisite
Now CLI 18.0.0
❗️ The `name` property in now.json is deprecated (https://zeit.ink/5F)
� Inspect: https://zeit.co/alenieto97/camitter/6b76zrggu [3s]
✅ Preview: https://camitter.alenieto97.now.sh [copied to clipboard] [20s]
� To deploy to production (camitter.now.sh), run `now --prod`
❗️ Zero-configuration deployments are recommended instead of a `builds` property in `now.json`. The "Build and Development Settings" in your Project will not apply.
Alejandro#DESKTOP-LOJH5G7 MINGW64 ~/Desktop/Programacion/Meower/server
HEROKU
Here i'm pretty sure im doing something wrong on the index.js or client.js or both. I saw tons of guides and have all the files necesary. When I deploy, the app simply doesn't work. Since I actually tried to adapt the code to work on Heroku I'm pretty sure the problem lies in the code itself. This is The folder:
node_modules
.gitignore
index.js
package_lock.json
client.js
favicon.ico
index.html
loading.gif
styles.css
Procfile
Index.js
const express = require('express');
//Cors permite que cualquiera se comunique con el server.
const cors = require('cors');
const Filter = require('bad-words');
const rateLimit = require('express-rate-limit');
const { Pool, Client } = require('pg');
const port = process.env.PORT;
const connectionString = 'postgres://gvvsunuvtdhxpq:e9d3239ab17ea6f38d0b6303dee62b7704b37574e5eb2783ca7edb868cc7192a#ec2-18-235-20-228.compute-1.amazonaws.com:5432/d7df9kofqifk5b'
const pool = new Pool({
connectionString: connectionString,
})
const filter = new Filter();
const app = express();
//ORDER MATTERS, WHAT IS FIRST GETS EXECUTED FIRST
app.enable('trust proxy');
app.use(cors());
//any incoming request that is JSON will pass
app.use(express.json());
//server, when you get a request run this function.
app.get('/',(request,response) => {
res.json({
message: 'Meower!'
});
});
app.get('/mews', async (req, res) => {
try {
const client = await pool.connect()
const result = await client.query('SELECT * FROM test_table');
const results = { 'results': (result) ? result.rows : null};
res.render('pages/mews', results );
client.release();
} catch (err) {
console.error(err);
res.send("Error " + err);
}
})
function isvalidmew(mew){
return mew.name && mew.name.toString().trim() !== '' &&
mew.content && mew.content.toString().trim() !== '';
}
//limit the submit rate
app.use(rateLimit({
windowMs: 30 * 1000,
max: 2
}));
//this will wait for incoming data and insert in database
app.post('/mews', (req,res) => {
if(isvalidmew(req.body)){
const mew = {
name: filter.clean(req.body.name.toString()),
content: filter.clean(req.body.content.toString()),
created: new Date()
};
mews
.insert(mew)
.then(createdMew => {
res.json(createdMew);
});
} else {
res.status(422);
res.json({
message:'Hey! Name and Content are required!'
});
}
});
app.listen(port, () => {
console.log('Listening on PORT');
});
Client.js
const form = document.querySelector('form');
const loadingElement = document.querySelector('.loading');
const mewsElement = document.querySelector('.mews');
const API_URL = 'https://camisite.herokuapp.com/mews';
loadingElement.style.display = '';
listallmews();
form.addEventListener('submit', (event) => {
event.preventDefault();
const formData = new FormData(form);
//We grab the stuff from the form
const name = formData.get('name');
const content = formData.get('content');
//We put it in an object
const mew = {
name,
content
};
//We send the data to the server
form.style.display = 'none';
loadingElement.style.display = '';
fetch(API_URL, {
method: 'POST',
body: JSON.stringify(mew),
headers : {
'content-type':'application/json'
}
}).then(response => response.json())
.then(createdMew => {
form.reset();
setTimeout(() => {
form.style.display = '';
},30000);
listallmews();
});
});
function listallmews(){
mewsElement.innerHTML = '';
fetch(API_URL)
.then(response => response.json())
.then(mews => {
console.log(mews);
mews.reverse();
mews.forEach(mew =>{
const div = document.createElement('div');
const header = document.createElement('h3');
header.textContent= mew.name
const contents = document.createElement('p')
contents.textContent= mew.content;
const date = document.createElement('small');
date.textContent = new Date(mew.created);
div.appendChild(header);
div.appendChild(contents);
div.appendChild(date);
mewsElement.appendChild(div);
});
loadingElement.style.display = 'none'
});
}
Procfile
web: node index.js
Package.json
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js"
},
"keywords": [],
"author": "CJ R. <cj#null.computer> (https://w3cj.now.sh)",
"license": "MIT",
"dependencies": {
"bad-words": "^1.6.3",
"cors": "^2.8.5",
"express": "^4.16.3",
"express-rate-limit": "^3.1.1",
"monk": "^6.0.6",
"morgan": "^1.9.1",
"pg": "^7.18.2"
},
"devDependencies": {
"nodemon": "^1.18.4"
}
}
I appreciate a lot any help to deploy on any of the two platforms, im trying to make the most out of this quarantine and have been trying to solve this for twenty hours straight. Cheers to any isolated folks!
Change index.js file
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Our app is running on port ${ PORT }`);
});
You can also refer https://help.heroku.com/P1AVPANS/why-is-my-node-js-app-crashing-with-an-r10-error
Im trying to find a way to allow user to click on the link only after a specific function has completed running. So here in my case I have ejs template where there are two links in parapgraphs. Clicking on the first one ("Run python") activates a script that takes some time to complete. Then only after it has finished (so the there is "finished" - which comes from the line: console.log('finished') printed on the console) the next link("See the table") would be clickable (or unhid or something like that).
<h1>Search for a movie</h1>
<form action="results" method="GET">
<input type="text" placeholder="search term" name="search">
<input type="submit">
</form>
<p> Run python </p>
<p> See the table </p>
Here is the app.js code
var express = require("express")
var app = express()
var request = require("request")
var PythonShell = require('python-shell');
app.set("view engine", "ejs")
app.engine('html', require('ejs').renderFile);
var thelist =[]
app.get("/", function(req, res){
res.render("search")
})
var jsondata = ""
app.get("/results", function(req, res){
var query = req.query.search
var url = "http://www.omdbapi.com/?s=" + query + "&type=series&apikey=thewdb"
request(url, function(error, response, body){
if(!error && response.statusCode == 200){
var data = JSON.parse(body)
res.render("results", {data: data})
}
})
})
app.get('/data', function(req, res) {
//viewname can include or omit the filename extension
res.render(__dirname + '/well.html');
});
app.get("/show/:id", function (req, res) {
var id = req.params.id;
thelist.push(id)
console.log(thelist);
res.redirect('/')
});
app.get("/run", function(req, res) {
var pyshell = new PythonShell('script2.py');
pyshell.send(JSON.stringify(thelist))
pyshell.on('message', function (message) {
// received a message sent from the Python script (a simple "print" statement)
jsondata += message
});
// end the input stream and allow the process to exit
pyshell.end(function (err) {
if (err){
throw err;
};
console.log('finished');
});
res.redirect('/')
thelist = []
});
app.listen(process.env.PORT, process.env.IP, function(){
console.log("Movie App has started!!!");
})
You could probably do it with ajax, as emil suggests in his answer,
but since you are using ejs template engine, why don't use it ?
(You just need to change the .html template file extension to .ejs).
Also, I think your best option here is to not use res.redirect.
It would be better to use res.render and pass a parameter to the view, set to false by default.
A basic example:
server.js
// ...
app.get("/", function (req, res) {
res.render("search", { active: false });
})
// ...
app.get("/run", function (req, res) {
// ...
pyshell.end(function (err) {
if (err) throw err;
console.log('finished');
res.render("search", { active: true });
});
});
search.ejs
<p>Run python</p>
<p>
<%if (active) { %>
See the table
<% } else { %>
See the table
<% } %>
</p>
Now the See the table link is only clickable if the python script is finish.
Summary
It should be done by using AJAX calls. Instead of using redirect in /run, you can make it return some JSON data which indicates success/error state of the job.
On click of Run python, it will run AJAX call instead of redirecting page to /.
on OnSuccess of AJAX call, you can enable see the table.
Code
HTML
<p><a id="run" href="/run"> Run python </a></p>
<p><a id="show-data" href="/data" style="pointer-events:none;"> See the table </a></p>
Frontend Javascript
$(function() {
$('#run').click(function(event) {
event.preventDefault();
$.get('/run', function() {
$('#show-data').css('pointer-events', 'all');
});
});
});
NodeJs
app.get("/run", function(req, res) {
...
// res.redirect('/');
res.json({ success: true });
});
U can prevent links by using prevent function Jquery
$("a").click(function() {
if (status == "1") {
return true;
} else {
return false;
e.preventDefault();
}
});
This is the function where I used to stop the user from navigating to other pages without running a function.
I Initialized a variable called status with value = 0
Then I incremented the variable once the function was success.
So if the status is 0 then the URL won't work, after finishing the function the status will be incremented to 1 and hence if the condition is true and it will return true statement. If not it will return false statement and it will be prevented using e.preventDefault()
Why don't you try socket.io?
Here is simplified code, but fully functional...
(Note: "msg" object is for example only, for further usage)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Title</title>
</head>
<body>
<h1>Search for a movie</h1>
<p> Run python </p>
<p><a id="table-data"> See the table </a></p>
<script src="/socket.io/socket.io.js"></script>
<script>
var msg = {
msg: "TestMsgSend",
iParam: 100,
sParam: "Test Param 1",
aParam: [1, 2, 3]
}
var socket = io();
socket.on("server:finished", function (msg) {
// msg = "TestMsgReceived", for further usage
console.log("\nId: " + socket.id + "\nmsg: " + msg.msg + "\niParam: " + msg.iParam + "\nsParam: " + msg.sParam + "\naParam: " + msg.aParam);
document.getElementById("table-data").setAttribute("href", "/data");
});
function runPython() {
socket.emit("client:run", msg);
}
</script>
</body>
</html>
app.js
var express = require("express");
var app = express();
var http = require("http").Server(app);
var io = require("socket.io")(http);
app.use("/", express.static(__dirname + "/"));
// ***************************************************************************
// ***************************************************************************
// ***** Your code
// ***************************************************************************
// ***************************************************************************
io.on("connection", function (socket) {
console.log("New connection with id: " + socket.id);
socket.on("client:run", function (msg) {
// msg = "TestMsgSend", for further usage
console.log("\nId: " + socket.id + "\nmsg: " + msg.msg + "\niParam: " + msg.iParam + "\nsParam: " + msg.sParam + "\naParam: " + msg.aParam);
// ***************************************************************************
// ***************************************************************************
// ***** Your code
// ***************************************************************************
// ***************************************************************************
msg.msg = "TestMsgReceived";
msg.iParam++;
msg.sParam = "Test Param 2";
msg.aParam.push(4, 5, 6)
io.emit("server:finished", msg);
});
});
// ***************************************************************************
// ***************************************************************************
// ***** Your code
// ***************************************************************************
// ***************************************************************************
http.listen(80, function () {
console.log("listening on *:80");
});
package.json
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.16.2",
"socket.io": "^2.0.4"
}
}
Start with node app.js and enjoy
Why not something like a simple guard variable? In your code:
var ready = false; // 1) the guard
app.get('/data', function(req, res) {
if (ready) { // 2) view execution blocked until guard is ready
res.render(__dirname + '/well.html');
}
});
app.get("/run", function(req, res) {
var pyshell = new PythonShell('script2.py');
pyshell.send(JSON.stringify(thelist))
pyshell.on('message', function (message) {
// received a message sent from the Python script (a simple "print" statement)
jsondata += message
});
// end the input stream and allow the process to exit
pyshell.end(function (err) {
if (err) {
throw err;
};
ready = true; // 3) if evetything is OK the guard is now ready
console.log('finished');
});
res.redirect('/')
thelist = []
});
I've looked through several stackoverflow articles and tried different ways of connection but none of them work. So far I've tried:
var mongodb = require('mongodb');
var uri = 'mongodb://Userxxx:Passxxx#ds0URI:PORT/heroku_appXXX';
mongodb.MongoClient.connect(uri, { server: { auto_reconnect: true } }, function (err, db) {
});
That crashed with the following error:
TypeError: Cannot call method 'connect' of undefined
Then I tried this:
mongo = require('mongodb')
Server = mongo.Server
Db = mongo.Db
BSON = mongo.BSONPure;
con = null;
server = new Server('xxxxx.mongolab.com', 'PORT', {auto_reconnect: true});
DBCon = new Db('xxxxx', server, {safe: false});
DBCon.open(function(err, db) {
if(!err) {
db.authenticate('xxxxx', 'xxxxx', function(err){
if(!err) con = db;
})
}
});
And that gave me an error: /app/node_modules/mongodb/lib/mongodb/connection/connection_pool.js:10
number') throw "host and port must be specified [" + host + ":" + port + "]"; host and port must be specified
Does anyone know the right way to do this?
I have used MongoClient in Heroku. The code doesn't look that different from what you have:
var MongoClient = require("mongodb").MongoClient;
MongoClient.connect(databaseString, function (err, result){
if (err) {
}
}
Because of the error you are getting (MongoClient is undefined), I wonder if your package.json file is correct. In my test it looks like this:
{
"name": "test",
"version": "0.0.1",
"dependencies": {
"express": "2.5.x", "mongodb": "1.2.14", "node-static": "0.7.0"
},
"engines": {
"node": "0.8.x",
"npm": "1.1.x"
}
}