I'm teaching myself Nodejs and am trying to populate a page with a list of nearby businesses' opening and closing hours from Yelp's API. I created a POST route to my page in Express, calling the Yelp API using the Yelp Fusion client. I am able to gather an array of ids which must be used in another endpoint in order to fetch the hours of operation, however I keep receiving TOO_MANY_REQUESTS_PER_SECOND errors when do this, despite setting the limit in the request.
Server.js
var express = require("express");
var app = express();
var yelp = require("yelp-fusion");
var bodyParser = require("body-parser");
app.use(express.static(__dirname + '/public'));
app.use(bodyParser.urlencoded({extended: true}));
app.set("view engine", "ejs");
let client = yelp.client("API_HIDDEN");
app.get("/", function(req,res){
res.render("landing");
});
///Initial request made to obtain business ids
app.post("/", function(req, res){
client.search({
term: 'cafe',
location: 'Oakland',
limit: 20
}).then(response => {
var ids = [];
var businesses = response.jsonBody.businesses;
var idName = businesses.map(el => {
ids.push(el.id);
});
// request separate endpoint, passing ids from the ```ids```array
for(var x = 0; x < businesses.length; x++){
client.business(ids[x]).then(response => {
console.log(response.jsonBody.hours);
})}.
res.render("search");
}).catch(e => {
console.log(e);
});
})
app.listen(3000);
I have tried calling client.businesses[id] both inside and outside a for loop but this resulted in errors too. I am confused on the behaviour of this as I am only making 20 calls, far below the minimum, but also how to possibly pass the ids if not for an array as I have run out of ideas. Thank you in advance for your help.
Spread out the api calls over time.
var delay = 1.1 * 1000; // 1.1 seconds in milliseconds
for(var x = 0; x < businesses.length; x++){
setTimeout(function(i){
client.business(ids[i]).then(response => {
console.log(response.jsonBody.hours);
});
},delay*x,x);
}
Related
I am trying to retrieve data from a html table and insert this in MySQL database. I am already able to do the reverse, which is retrieve the information from the database and display it in same table using ejs template. I can also insert raw/JSON data into MySQL, but I'm unable to extract the data from same table because I am unable to reference that table from the server side (the same way body parser does with form data).
I have searched the web, all tutorials just do an insert to database using json data, nobody is retrieving data first from html table.
With below code I can loop through table data using plain javascript.
var table = document.getElementById('vehiclesTB');
for (var i = 1; i < table.rows.length; i++) {
if (table.rows[i].cells.length) {
var vehicleTag = (table.rows[i].cells[0].textContent.trim());
}
}
How do I pass retrieve data from html table to my controller(server side)? I am unable to reference html table directly from my server file (app.js).
My app.js file:
var express = require('express')
, routes = require('./routes')
, controls = require('./routes/controls')
, http = require('http')
, path = require('path');
var app = express();
var mysql = require('mysql');
var bodyParser =require("body-parser");
var pool = mysql.createConnection({
connectionLimit: 100,
host: 'localhost',
database: 'vehicluster',
user: 'motor',
password: '',
debug: false
});
pool.connect();
// all environments
app.set('port', process.env.PORT || 8080);
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'public')));
app.post('/vehicle', controls.vehicle);
//Middleware
app.listen(8080)
My controls.js file.
exports.vehicle = function(req, res){
var table = document.getElementById('vehiclesTB');//how to read this
table in ejs
for (var i = 1; i < table.rows.length; i++) {
if (table.rows[i].cells.length) {
var vehicleTag = (table.rows[i].cells[0].textContent.trim());
var vehicleMake = (table.rows[i].cells[1].textContent.trim());
var vehicleModel = (table.rows[i].cells[2].textContent.trim());
var price = (table.rows[i].cells[3].textContent.trim());
var quantity = (table.rows[i].cells[4].textContent.trim());
}
}
var sql = 'insert into Vehicle(make, model, price, quantity) values
(?,?,?,?,?)';
pool.query(sql,[vehicleMake, vehicleModel, price, quantity],
(err,data)=>{
if(err){
console.log(err);
return
}else{
console.log(data);
}
};
The HTML table is showing relevant item (table), place table data into mysql database. I can already retrieve to table:
<div style="overflow-x: auto;">
<table id="customers">
<tbody id="mytbody">
<tr>
<th>Make</th>
<th>Model</th>
<th>price</th>
<th>quantity</th>
</tr>
<tr>
<th>toyota</th>
<th>camry</th>
<th>200</th>
<th>5</th>
</tr>
<tr>
<th>honda</th>
<th>civic</th>
<th>400</th>
<th>7</th>
</tr>
</tbody>
</table>
</div>
I am getting errors as you would expect, getElementById is client side, null value etc, database is not updated. Most tutorials online show the reverse, which is to insert database values into html table, instead of the other way around. Any help with real table example/route will be appreciated.
If you need to have a client-side HTML table made available on the server, then you will need to add an ajax endpoint at the server and code to send the HTML data (see the axios library).
I am not sure of your use case as it seems the data at the client side should already be available at the server since you rendered it. It may not be in HTML, but the data should exist there. Unless of course you are getting the HTML table from another source (or perhaps this is just an exercise in HTML parsing??).
Here is an update to show how to use axios. Note though that you still need to investigate that library to learn how to handle errors or even if you need to do other things upon success.
In your front end:
var table = document.getElementById('vehiclesTB');
var postBody = [];
for (var i = 1; i < table.rows.length; i++) {
if (table.rows[i].cells.length) {
var vehicle = {
vehicleTag: (table.rows[i].cells[0].textContent.trim())
vehicleMake: (table.rows[i].cells[1].textContent.trim()),
vehicleModel: (table.rows[i].cells[2].textContent.trim()),
price: (table.rows[i].cells[3].textContent.trim()),
quantity: (table.rows[i].cells[4].textContent.trim())
}
postBody.push(vehicle);
}
}
axios({ // should add error handling as appropriate
method: 'post',
url: '/vehicle',
data: postBody
});
Then on your server side, modify your controls.js:
exports.vehicle = function(req, res) {
var table = req.body; // assumes you have used bodyparser middleware to parse JSON into an object
for (var i = 1; i < table.length; i++) {
var vehicle = table[i];
var sql = 'insert into Vehicle(make, model, price, quantity) values ( ? , ? , ? , ? , ? )';
pool.query(sql, [vehicle.vehicleMake, vehicle.vehicleModel, vehicle.price, vehicle.quantity],
(err, data) => {
if (err) {
console.log(err);
return
} else {
console.log(data);
}
});
}
};
Also, I would suggest you look at Array.forEach for looking over an array instead of the for loop method you are using (see MDN documentation)
I want users to fill out a form embedded a section of an HTML website, and have their submitted responses be updated every time on the same HTML file, rather than displaying their responses on a separate output.ejs file. I just don't know how beyond this point. What would I change in my server file?
var express = require('express')
var app = express()
var formdata = [];
var bodyParser = require('body-parser');
var urlencodedParser = bodyParser.urlencoded({ extended: true });
app.use(urlencodedParser);
app.get('/', function (req, res) {
res.render('index');
})
app.use(express.static(__dirname + '/public'));
app.set('view engine', 'ejs');
app.post('/processform', function(req,res) {
let data = new Object();
data.street = req.body.street;
data.pet = req.body.pet;
formdata.push(data);
let passedindata = new Object();
passedindata.formdata = formdata;
res.render("output.ejs", passedindata);
});
I would make another API endpoint that return formdata. After the user successfully post a response, instead of rendering output.ejs, have your form page make this API call to get the newly updated formdata, then process on the frontend as you please.
I am a new user of node.js and mongodb and still learning. Please excuse if the question seems very simple. My node.js MongoDB query script (hello.js) is-
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var url = 'mongodb://localhost:27017/flood';
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
console.log("Connected correctly to server.");
var collec_name="99"
var field_name ="data1"
var value=311
db.collection(collec_name).find({data0:value}, {[field_name]:1, _id:0}).toArray(function(err, result) {
if (err) throw err;
console.log(result);
db.close();
});
});
The query runs fine with command- node hello.js and got the expected value result (for instance, output value of result is 0.000115). Note that var collec_name="99", var field_name ="data1" and var value=311 contain fixed values.
My HTML file (index.html) is-
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
<script>
var c_n = "99";
var f = "data1";
var v = 311;
document.getElementById("demo").innerHTML = 0.000115;
</script>
</body>
</html>
Now, I want to pass the values of variable c_n, v and f from index.html to hello.js by replacing three statements of hello.js as-
var collec_name=c_n
var field_name = f
var value = v
Then, I want to pass value of result from hello.js to the index.html by replacing one statement of index.html as-
document.getElementById("demo").innerHTML = result;
So, how can I achieve these parameter passing so that if I run the index.html page, I can display the value of result on the web? Any solution script based on my scripts will be highly appreciated.
To send data between your back-end and your client you have to use AJAX, socket.io or WebSockets.
If you only have to update the back-end if the clients wants to you should use AJAX. If your client has to be notified by the back-end (Server), you should use socket.io or WebSockets for that.
Because you are using NodeJs, i would recommend you to use socket.io.
Just have a look at it:
https://socket.io/
Here a example for your code:
First install the package:
npm install -S socket.io
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
// add socket io
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
// connect to port
app.listen(3030);
var url = 'mongodb://localhost:27017/flood';
// setup server
io.on('connection', function (socket) {
// add event
socket.on('data', function (data) {
// execute after event was emitted
MongoClient.connect(url, function (err, db) {
assert.equal(null, err);
console.log("Connected correctly to server.");
var collec_name = data.collec;
var field_name = data.field;
var value = data.value
db.collection(collec_name).find({ data0: value }, { [field_name]: 1, _id: 0 }).toArray(function (err, result) {
if (err) throw err;
// TODO add emmit
console.log(result);
db.close();
});
});
});
});
HTML:
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
<script src="path/to/socket.io"></script>
<script>
var socket = io('http://localhost');
// send message
socket.emit('data', {
collec: "99",
field: "datal",
value: 311
});
// TODO add listener
document.getElementById("demo").innerHTML = 0.000115;
</script>
</body>
</html>
Finally, I was able to solve the problem. As I didn't find any perfect solution on net, I thought it will be helpful for other users (who are facing similar problem) if I post a general solution to a similar problem here. Please excuse if this is not the right place to post the solution.
My Solution: This is not the exact solution of my above example but I think it is better to provide a general solution to a similar problem so that anyone can always modify/update this solution according to his/her example/need as basic approach will be always same. At first, you need to have http, express and body-parser and you can do by following the commands:
npm install http
npm install express
npm install body-parser --save
A general problem: Suppose, I have two numbers (for instance a = 20 and b = 24 in the client HTML page and I want to sum up the numbers from the server side and get the summation result (sum = 44) back in the client side to display in the HTML page. Then use the following nodejs and ejs scripts-
index.ejs:
<html>
<head>
<title>Example solution</title>
<script src="http://code.jquery.com/jquery-1.6.2.min.js"></script>
<script type="text/javascript">
$(function(){
$('#loadRequest').click(function(e) {
e.preventDefault();
console.log('Load_button clicked');
var data = {};
data.a = 20; //input
data.b = 24; //input
$.ajax({
type: 'POST',
data: JSON.stringify(data), //input data to be sent to the server
contentType: 'application/json',
url: 'http://localhost:80/endpoint',
success: function(res) {
console.log('success');
console.log(res);
$("#demo").html(res); //summation displayed in the HTML page
}
});
});
});
</script>
</head>
<body>
<p id ="demo"></p>
<button id="loadRequest">Load</button>
</body>
</html>
server.js:
var http = require('http');
var express = require('express');
var app = express();
app.set('view engine', 'ejs'); //tell Express we're using EJS
app.set('views', __dirname + '/views'); //set path to *.ejs files
app.use('/public', express.static(__dirname + '/public'));
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
app.get('/', function(req, res) {
//render index.ejs file
res.render('index');
});
app.post('/endpoint', function(req, res){
var x = req.body.a; //received input 1 from client side
var y = req.body.b; //received input 2 from client side
console.log(x);
console.log(y);
var sum =x+y;
console.log(sum);
res.send(String(sum)); //sending summation to the client
});
http.createServer(app).listen(80);
It worked perfectly. Please let me know if you have any comment/feedback.
You can either implement an API yourself using AJAX, WebSockets or socket.io - or you can go ahead and take a look into Express framework.
Setting up a Node.js server using Express will not only provide you access to a rich API interface, it would also make your task much easier.
Using it, you can set up a simple route like this:
app.post('/compute', function(req, res){
// compute 'result'
res.send(result);
});
i have one doubt regarding socket.io.I have two type of user i.e-admin,client .First admin will create userid and join to the room.I need when user will join room the admin should get response and need help regarding this.
My working codes are given below.
server.js:
var port=8888;
var express=require('express');
var morgan = require('morgan');
var http=require('http');
var bodyParser= require('body-parser');
var methodOverride = require('method-override');
var mongo = require('mongojs');
var database='Oditek';
var collections=['video'];
var app= express();
var server=http.Server(app);
var io=require('socket.io')(server);
var db = mongo.connect("127.0.0.1:27017/"+database, collections);
app.use(express.static(__dirname + '/public')); // set the static files location /public/img will be /img for users
app.use(morgan('dev')); // log every request to the console
app.use(bodyParser.urlencoded({ extended: false })) // parse application/x-www-form-urlencoded
app.use(bodyParser.json()) // parse application/json
app.use(methodOverride()); // simulate DELETE and PUT
db.on('ready', function () {
console.log('database connected')
});
app.get('/',function(req,res){
res.sendfile('view/login.html');
});
app.post('/login',function(req,res){
var username=req.body.username;
var password=req.body.userpassword;
if(username && password){
db.video.findOne({
username:username,
password:password
},function(err,doc){
if(doc){
console.log('login',doc);
res.send(doc);
}
if(err){
console.log('login12',err);
res.send("could not login");
}
});
}
});
app.get('/video',function(req,res){
res.sendfile('view/video.html');
});
//socket----programming//
var roomid;
io.on('connection',function(socket){
//console.log(socket);
roomid=socket.handshake.query.roomid;
var usertype=socket.handshake.query.usertype;
socket.join(roomid);
});
server.listen(port);
console.log('server is listening on the port'+port);
My client side code is given below.
function videoBroadCasting(uType){
var messageGateWay;
if(uType=='admin'){
var userid = getRandomString();
$('#styled').val('http://localhost:8888/video?usertype=client & id='+userid);
messageGateWay=io('http://localhost:8888/?roomid='+userid+'usertype='+uType);
}
if(uType=='user'){
messageGateWay=io('http://localhost:8888/?usertype='+uType);
}
messageGateWay.on('connect',function(){
console.log('socket get connected');
});
}
function getRandomString() {
return (Math.random() * new Date().getTime()).toString(36).replace(/\./g, '');
}
function getQuery(key){
var temp = location.search.match(new RegExp(key + "=(.*?)($|\&)", "i"));
if(!temp) return;
return temp[1];
}
After client is joining the room the admin should get one notification.Please help me to do this.
One simple solution is to save the socket object from the admin in the server when the admin joins the room. Then, when some other user join the room, simply emit a message to that socket from the admin/admins. Just keep an array update with the admins actually logged in the room.
Something like:
var socketAdmin = {};
io.on('adminJoins',function(socket){
socketAdmin = socket;
roomid=socket.handshake.query.roomid;
var usertype=socket.handshake.query.usertype;
socket.join(roomid);
});
io.on('clientJoins',function(socket){
roomid=socket.handshake.query.roomid;
socketAdmin.emit('newClient', {socketClient: socket, roomId: roomid};
var usertype=socket.handshake.query.usertype;
socket.join(roomid);
});
In this example, the client sends a message 'adminJoins' if you are an admin, or 'clientJoins' ir you are a client, you can send that checking the uType var you have. In case a new client joins the room, the admin recieve a 'newClient' message with the socket of the client and the roomId (just an example).
Im a node JS beginner and i need help with exporting the console log data into HTML page.
I found this great example at the GitHub: https://github.com/benbuckman/nodejs-ebay-api
my problem is this: I managed to implement it with my needs - but I don't manage to extract the data out of the console log ! I simply want to display it in the browser and not in the console log.
Any suggestions ?
Currently im working on the "single" example - here's my code so far, which has many errors:
// example simple request to FindingService:findItemsByKeywords
var ebay = require('../index.js');
var http = require('http');
var express = require('express');
var app = express();
var io = require('socket.io');
app.set('port', process.env.PORT || 5000);
app.get('/get', function(req, res) {
console.log('inside get');
// for avoiding crossbrowser-error
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.header('Content-Type','application/json');
var params = {};
params.keywords = [ "cat"];
params['paginationInput.entriesPerPage'] = 10;
ebay.ebayApiGetRequest({
serviceName: 'FindingService',
opType: 'findItemsByKeywords',
appId: 'MYAPPID', // FILL IN YOUR OWN APP KEY, GET ONE HERE: https://publisher.ebaypartnernetwork.com/PublisherToolsAPI
params: params,
// filters: filters,
parser: ebay.parseItemsFromResponse // (default)
},
// gets all the items together in a merged array
function itemsCallback(error, items) {
if (error) throw error;
console.log('Found', items.length, 'items');
for (var i = 0; i < items.length; i++) {
console.log('- ' + items[i].title);
}
}
);
});
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
console.log('Listening on port 5000...');
It looks like you're using Express, and specify a single GET API endpoint on the URL /get. From what I understand, you want to see the output from the browser and not just the console (the console you're able to see with the console.log messages). Express will return to the user who makes the HTTP request what you put in res.send(). So for example, if you were to add:
res.send("hello");
to the end of the `app.get' function, you would see "hello" in the browser. Note that you can only do that once, so you'll need to bundle all the information you want to send to the browser in an object, and then send that.
It looks like what you want to see is the data collected from within the itemsCallback function. So to make things simple, you could just send the items back. For instance:
function itemsCallback(error, items) {
if (error) throw error;
console.log('Found', items.length, 'items');
for (var i = 0; i < items.length; i++) {
console.log('- ' + items[i].title);
}
res.send(items); // sends the items in the HTTP response
}
As a side note, you don't need to include the http module, and instead can start the server like this:
app.listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port'));
});