Simply: I want to do a forloop of routes with incrementing numbers in their URL since I am expecting to have around 100 entries with the same format.
Without the forloop:
app.get('/day1', (req, res) =>{
res.render('pages/day1/day1.ejs')
});
app.get('/day2', (req, res) =>{
res.render('pages/day2/day2.ejs')
});
app.get('/day3', (req, res) =>{
res.render('pages/day3/day3.ejs')
});
I've tried this forloop:
for(i=1; i<4; i++){
app.get('/day' + i.toString(), (req,res) =>{
res.render('pages/day'+ i.toString() +'/day' + i.toString())
})
};
This forloop "works", but only for the last pass of the forloop (in this case for '/day3').
In this scenario:
For '/day2' and '/day1' I get a "Cannot GET /day2" or "Cannot GET /day1".
Even worse, if I try to play around with the initial parameters of the forloop, let's say (i=2;i<3;i++), I get weird behaviors like the /day3 link redirecting me to the /day4 link when it should not even be included.
Does this have something to do with my browser cache history?
You are following wrong apporch,
here, by Changing Route to somthing like this,
app.get('/day/:id', (req, res) =>{
let day = req.params.id
// use the template string
res.render(`pages/day${day}/day${day}.ejs`)
});
api call will be ( just example if you are using axios at client side ),
API_URL will be your backend app url,
axios.get(`${API_URL}/day/1`)
you will get desired output according to your need.
No sane person loops routes like this. You'd want to employ dynamic routing like this:
app.get('/:day', (req , res) => {
const { day } = req.params
res.render(`pages/${day}/${day}.ejs`)
})
If you truly want to do it your way, you could try building an array first like this:
const days = []
for (let i = 0; i < 100; i++) {
days.push("day" + i.toString())
}
Then build the routes:
days.forEach(day => {
app.get("/" + day, (req, res) => {
res.render(`pages/${day}/${day}.ejs`)
})
})
Related
I'm making a website which tracks kill statistics in a game but I can only access 50 key value pairs per request, so to make sure that my data is accurate I want to make a request about every 30 seconds.
I feel like I may have gone wrong at some stage in the implementation. Like, maybe there is a way to make requests that doesn't involve using
express.get('/route/', (req, res) => { //code })
syntax and I just don't know about it. In short, what I want is for the database to be updated every 30 seconds without having to refresh the browser. I've tried wrapping my get request in a function and putting it in set interval but it still doesn't run.
const express = require('express');
const zkillRouter = express.Router();
const axios = require('axios');
const zkillDbInit = require('../utils/zkillTableInit');
const sqlite3 = require('sqlite3').verbose();
zkillDbInit();
let db = new sqlite3.Database('zkill.db');
setInterval(() => {
zkillRouter.get('/', (req, res)=>{
axios.get('https://zkillboard.com/api/kills/w-space/', {headers: {
'accept-encoding':'gzip',
'user-agent': 'me',
'connection': 'close'
}})
.then(response => {
// handle success
const wormholeData = (response.data)
res.status(200);
//probably not the best way to do this but it's fine for now.
for (let i = 0; i < Object.keys(wormholeData).length; i++) {
const currentZKillId = Object.keys(wormholeData)[i]
const currentHash = Object.values(wormholeData)[i]
let values = {
$zkill_id: currentZKillId,
$hash: currentHash
};
//puts it in the database
db.run(`INSERT INTO zkill (zkill_id, hash) VALUES ($zkill_id, $hash)`,
values
, function(err){
if(err){
throw(err)
}
})
}
})
})
}, 1000)
module.exports = zkillRouter;
One thing I have considered is that I don't necessarily need this functionality to be part of the same program. All I need is the database, so if I have to I could run this code separately in say, the terminal as just a little node program that makes requests to the api and updates the database. I don't think that would be ideal but if it's the only way to do what I want then I'll consider it.
clarification: the .get() method is called on zkillRouter which is an instance of express.Router() declared on line two. This in turn links back to my app.js file through an apiRouter, so the full route is localhost:5000/api/zkill/. That was a big part of the problem, I didn't know you could call axios.get without specifying a route, so I was stuck on this for a while.
I fixed it myself.
(edit 4)
I was using setInterval wrong.
I just got rid of the router statement as it wasn't needed.
I definitely need to tweak the interval so that I don't get so many sql errors for violating the unique constraint. Every 5 minutes should be enough I think.
Don't throw an error.
function myfunction(){
axios.get('https://zkillboard.com/api/kills/w-space/', {headers: {
'accept-encoding':'gzip',
'user-agent': 'me lol',
'connection': 'close'
}})
.then(response => {
// handle success
const wormholeData = (response.data)
for (let i = 0; i < Object.keys(wormholeData).length; i++) {
const currentZKillId = Object.keys(wormholeData)[i]
const currentHash = Object.values(wormholeData)[i]
let values = {
$zkill_id: currentZKillId,
$hash: currentHash
};
db.run(`INSERT INTO zkill (zkill_id, hash) VALUES ($zkill_id, $hash)`,
values
, function(err){
if(err){
return console.log(i);
}
})
}
})
}
setInterval(myfunction, 1000 * 30)
I wrote this function to get a document from the end of the collection in MongoDB. When I try calling this function in index.js, it returns undefined.
index.js:
app.get('/', authenticate, function(req, res){
// console.log("DATA: " + getWorldStatsData());
everything = {
worldstats: getWorldStatsData(),
}
res.render('index', {
data: everything
})
})
and my function:
function getWorldStatsData(){
db.collection('worldstats').find({}).sort({"statistic_taken_at":-1}).limit(1).toArray((err, stats)=>{
return stats
})
// return stats
}
As jonrsharpe suggested, this is happening because the code that fetches the data is asyncroous.
That means you need to implement some kind of callback to notify the surrounding function when the operation is complete
A simple example:
index
app.get('/', authenticate, async function(req, res){
// console.log("DATA: " + getWorldStatsData());
everything = {
worldstats: await getWorldStatsData(),
}
res.render('index', {
data: everything
})
})
your funciton:
function getWorldStatsData(){
return db.collection('worldstats').find({}).sort({"statistic_taken_at":-1}).limit(1).toArray((err, stats)=>{
return stats
})
// return stats
}
Please take a look at the link provided by jonrsharpe for a better understanding
So I sit on the route defined as /article/:id on the client, and I query the server API like this:
const res = await axios.get(url + '/api/article')
(Don't worry about url, it's just to get the absolute path.)
Then I have my route:
router.get('/article', function(req, res) {
//I want to find the id from the params
//Trying fucking everything
console.log("host", req.get('host')) // 'localhost:3000'
console.log("url", req.url) // '/article'
console.log("query", req.query) // '{}'
})
Apparently this is crazy stuff in the Express/axios world, because I've spent the entire day trying to find out how to do this, but there is NO information out there on this subject.
How do I accomplish this stupidly simple task?
Your request is
const res = await axios.get(url + '/api/article')
You do not send an id. If you want to give a query you should
const res = await axios.get(url + '/api/article?id=theId')
and use req.query.id
or you have to change the route to
router.get('/article/:id', ....
call const res = await axios.get(url + '/api/article/theId')
and use req.params.id
router.get('/article/:id', function(req, res) {
//I want to find the id from the params
console.log(req.params.id)
})
Taken from here: https://expressjs.com/en/guide/routing.html
I have the following code where I am using the splice function to pass only the first 10 /JSON objects to the JADE template.
app.get('/index', function(req, res) {
new models.Condos()
.query('orderBy', 'age', 'asc')
.fetch()
.then(function(names) {
var name = names.splice(0,10);
res.render('index', {
names: name.toJSON()
});
});
});
};
Is there any way where i could restrict the query itself to return only the first 10 records instead of splicing the array to do that (use the offset and limit parameters) ?
You can write a knex query to achieve this it will look something like:
app.get('/index', function(req, res) {
knex.select('*')
.from('condos')
.limit(10)
.then(function(names) {
res.render(names);
});
});
You will also need to require knex in your router file.
What I was looking for was something more along these lines.
app.get('/index', function(req, res) {
new models.Condos()
.query('orderBy', 'age', 'asc')
.query('limit','10')
.fetch()
.then(function(names) {
var name = names.splice(0,10);
res.render('index', {
names: name.toJSON()
});
});
});
};
You can use the Pagination plugin from Bookshelf.
models.Condos.fetchPage( {page:1, pageSize:10} )
Note: for the first page if the page size is 10, you can leave out the params and just
models.Condos.fetchPage()
I'm trying to use node js and mysql, along with rendering data from my database into a view.
The issue is, how do I render multiple pieces of data within 1 view (Using jade template).
router.get('/about', function(req, res) {
var animalsData = sequelize.query("SELECT * FROM animals").success(function(rows) {
return rows;
});
console.log(animals); // returns 'undefined'
var humansData = sequelize.query("SELECT * FROM humans").success(function(rows) {
return rows;
});
console.log(humans); // returns 'undefined'
res.render('about', { animals: animalsData, humans: humansData });
});
As you can see, how can I get the data and then pass it into the view? Using nested callbacks can get messy if theres 5 or 6 bits of data (mysql queries) I wish to pass into the view?
Thanks
First of, those returns don't work. The code that you are running is asynch. I would suggest you to use promises:
var q = require("q");
router.get('/about', function(req, res) {
var animalDeferer = q.defer(),
humanDeferer = q.defer;
sequelize.query("SELECT * FROM animals").success(function(rows) {
animalDeferer.resolve(rows);
});
sequelize.query("SELECT * FROM humans").success(function(rows) {
humanDeferer.resolve(rows);
});
Q.all([animalDeferer.promsie, humanDeferer.promise]).spread( function(animalsData, humansData) {
res.render('about', { animals: animalsData, humans: humansData });
});
});
I wrote this directly on the answerbox so it may have typos.
q - https://github.com/kriskowal/q