Is This Logic About Node.JS - Router True? - node.js

i'm new in node.js. i made routes/index like this and i don't know is it good or not?
my code worked perfectly but :
1 - can anyone explain is this code standard?
2 - can i use external folder/file for my controller ? like : controller/users/index.js
controller/api/index.js
routes/index.js
var express = require("express")
var router = express.Router()
var request = require("request");
let index = {
// ## Controls
getBTC: function () {
request.get("http://api.coindesk.com/v1/bpi/currentprice.json", (err, response, body) => {
if (err) {
return console.dir(err);
}
rate = JSON.parse(body).bpi.USD.rate
time = JSON.parse(body).time.updated
})
},
// ## Routes
indexRoute: function () {
router.get('/', function (req, res, next) {
res.render('common/index', {
title: 'Index Title',
rate: this.rate,
time: this.time
})
})
},
testRoute: function () {
router.get('/test', function (req, res, next) {
res.render('common/test', {
title: 'Test Title',
rate: this.rate
})
})
}
}
index.getBTC() //-> Enable For All Routes
index.indexRoute()
index.testRoute()
module.exports = router
views/common/index.pug
extends ../layout
block content
p #{rate}
h1 #{time}

Related

Post Request stuck on Postman

I am learning to build API using Node.js, Express and MongoDB. I am on early learning phase.
My code are as follow.
const app = express();
const mongojs = require("mongojs");
const { body, param, validationResult } = require("express-validator");
const db = mongojs("travel", ["records"]);
const bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.get("/api/records", function (req, res) {
const options = req.query;
const sort = options.sort || {};
const filter = options.filter || {};
const limit = 2;
const page = parseInt(options.page) || 1;
const skip = (page - 1) * limit;
for (var i in sort) {
sort[i] = parseInt(sort[i]);
}
db.records
.find(filter)
.sort(sort)
.skip(skip)
.limit(limit, function (err, data) {
if (err) {
return res.sendStatus(500);
} else {
return res.status(200).json({
meta: {
filter,
sort,
skip,
limit,
page,
total: data.length,
},
data,
links: {
self: req.originalUrl,
},
});
}
});
});
app.post("/api/records", function (req, res) {
db.records.insert(req.body, function (err, data) {
if (err) {
return res.status(500);
}
const _id = data._id;
res.append("Location", "/api/records/" + _id);
return res.send(201).json({
meta: { _id },
data,
});
});
});
app.listen(8000, function () {
console.log("Server running at port 8000...");
});
When I try GET request on Postman, it works fine. But when I try POST request, it shows like the following. error msg image link.
Please let me know what is wrong here.
Thanks in advance

Generating Selection List with Cosmos DocumentDB

I am looking to generate a selection list with data from a Cosmos documentDB, each list will be independent of each other. I am currently only able to generate one list and the second list is a replica of the first, it won't read both. Any help will be appreciated, thanks!
App.js
const CosmosClient = require('#azure/cosmos').CosmosClient
const config = require('./config')
const TaskList = require('./routes/tasklist')
const TaskDao = require('./models/taskDao')
const express = require('express')
const path = require('path')
const logger = require('morgan')
const cookieParser = require('cookie-parser')
const bodyParser = require('body-parser')
const app = express()
// view engine setup
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'jade')
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))
app.use(cookieParser())
app.use(express.static(path.join(__dirname, 'public')))
//Todo App:
const cosmosClient = new CosmosClient({
endpoint: config.host,
key: config.authKey
})
const taskDao = new TaskDao(cosmosClient, config.databaseId, config.containerId)
const taskDao2 = new TaskDao(cosmosClient, config.databaseId2, config.containerId2)
const taskList = new TaskList(taskDao,taskDao2)
taskDao
.init(err => {
console.error(err)
})
.catch(err => {
console.error(err)
console.error(
'Shutting down because there was an error settinig up the database.'
)
process.exit(1)
})
taskDao2
.init(err => {
console.error(err)
})
.catch(err => {
console.error(err)
console.error(
'Shutting down because there was an error settinig up the database.'
)
process.exit(1)
})
app.get('/', (req, res, next) => taskList.showClosurePlanList(req, res).catch(next))
app.get('/', (req, res, next) => taskList.showTestList2(req, res).catch(next))
app.post('/addtask', (req, res, next) => taskList.addTask(req, res).catch(next))
app.set('view engine', 'jade')
// catch 404 and forward to error handler
app.use(function(req, res, next) {
const err = new Error('Not Found')
err.status = 404
next(err)
})
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message
res.locals.error = req.app.get('env') === 'development' ? err : {}
// render the error page
res.status(err.status || 500)
res.render('error')
})
module.exports = app
taskDao.js
// #ts-check
const CosmosClient = require('#azure/cosmos').CosmosClient
const debug = require('debug')('todo:taskDao')
// For simplicity we'll set a constant partition key
const partitionKey = undefined
class TaskDao {
/**
* Manages reading, adding, and updating Tasks in Cosmos DB
* #param {CosmosClient} cosmosClient
* #param {string} databaseId
* #param {string} containerId
*/
constructor(cosmosClient, databaseId, containerId) {
this.client = cosmosClient
this.databaseId = databaseId
this.collectionId = containerId
this.database = null
this.container = null
}
async init() {
debug('Setting up the database...')
const dbResponse = await this.client.databases.createIfNotExists({
id: this.databaseId
})
this.database = dbResponse.database
debug('Setting up the database...done!')
debug('Setting up the container...')
const coResponse = await this.database.containers.createIfNotExists({
id: this.collectionId
})
this.container = coResponse.container
debug('Setting up the container...done!')
}
async find(querySpec, querySpec2) {
debug('Querying for items from the database')
if (!this.container) {
throw new Error('Collection is not initialized.')
}
const { resources } = await this.container.items.query(querySpec,querySpec2).fetchAll()
return resources
}
async addItem(item) {
debug('Adding an item to the database')
item.date = Date.now()
item.completed = false
const { resource: doc } = await this.container.items.create(item)
return doc
}
async getItem(itemId) {
debug('Getting an item from the database')
const { resource } = await this.container.item(itemId, partitionKey).read()
return resource
}
}
module.exports = TaskDao
tasklist.js
const TaskDao = require("../models/taskDao");
class TaskList {
/**
* Handles the various APIs for displaying and managing tasks
* #param {TaskDao} taskDao
*/
constructor(taskDao,taskDao2) {
this.taskDao = taskDao;
this.taskDao2 = taskDao2;
}
async showClosurePlanList(req, res) {
const querySpec = {
query: "SELECT * FROM root r WHERE r.ClosurePlanList=#ClosurePlanList",
parameters: [
{
name: "#ClosurePlanList",
value: "yes"
}
]
};
const items = await this.taskDao2.find(querySpec);
res.render("index", {
title: "Form",
tasks: items
});
}
async showTestList2(req, res) {
const querySpec2 = {
query: "SELECT * FROM root r WHERE r.completed=#completed",
parameters: [
{
name: "#completed",
value: true
}
]
};
const items2 = await this.taskDao.find(querySpec2);
res.render("index", {
title: "Form",
tasks: items2
});
}
async addTask(req, res) {
const item = req.body;
await this.taskDao.addItem(item);
res.redirect("/");
}
}
module.exports = TaskList;
So I have one list - Closure Plan List, that currently looks at ClosurePlanList DocumentDB (which is perfect).
How do I get the second list - Test List 2, to look at the TestList2 DocumentDB?
I attempted to add do something like this but it is only reading one app.get at a time. I'm thinking this is where my issue is. Which ever app.get is on top seems to be the only one that is read.
app.get('/', (req, res, next) => taskList.showClosurePlanList(req, res).catch(next))
app.get('/', (req, res, next) => taskList.showTestList2(req, res).catch(next))
async find(querySpec, querySpec2) {
debug('Querying for items from the database')
if (!this.container) {
throw new Error('Collection is not initialized.')
}
const { resources } = await this.container.items.query(querySpec,querySpec2).fetchAll()
return resources
}
async showTestList2(req, res) {
const querySpec2 = {
query: "SELECT * FROM root r WHERE r.completed=#completed",
parameters: [
{
name: "#completed",
value: true
}
]
};
const items2 = await this.taskDao.find(querySpec2);
res.render("index", {
title: "Form",
tasks: items2
});
}
Example from here: https://learn.microsoft.com/en-us/azure/cosmos-db/sql-api-nodejs-application#_Toc395783181
If you want to get data and show them in : http://localhost:3000 , you should modify both views/index.jade and showTasks function in routes/tasklist.js.
I implemented a simple demo for you. Firstly, go to routes/tasklist.js, replace showTasks function with code below :
async showTasks(req, res) {
const querySpec = {
query: "SELECT * FROM root r WHERE r.completed=#completed",
parameters: [
{
name: "#completed",
value: false
}
]
};
const items = await this.taskDao.find(querySpec);
const itemsFromCollection1 = await this.taskDao.find("SELECT * FROM r");
const itemsFromCollection2 = await this.taskDao2.find("SELECT * FROM r");
res.render("index", {
title: "My ToDo List ",
tasks: items,
list1 : itemsFromCollection1,
list2 : itemsFromCollection2
});
}
Go to views/index.jade , append the code below to show your list1 and list2 data:
label data from collection1
select(id="demo1")
-for(var i = 0;i<list1.length;i++){
option(value="#{i}") #{list1[i].name}
-}
label data from collection2
select(id="demo2")
-for(var i = 0;i<list2.length;i++){
option(value="#{i}") #{list2[i].name}
-}
With steps are done, you can run the project and test it :
Hope it helps . Pls mark it as an answer if it is helpful for you . If you have any further questions, pls post a new query and let me know the link .

A lot of routes in one module.exports

// app.js
const express = require("express");
const app = express();
let jsonController = require("./jsonController.js");
app.get("/readJson", jsonController);
app.listen(1337, () => {
console.log("Listening");
});
// jsonController.js
module.exports = () => {
< --- here --- >
};
Can I find out in <--- here ---> from route it was called?
Something like this:
// jsonController.js
module.exports = () => {
if called from "/readJson" {
(res, req) => {
res.send("FROM READJSON"); }
}
};
Thanks for any help.
What you need is req.route.path.
If controller is configured as app.get("/readJson", jsonController); and app.get("/readJson2", jsonController);, then in jsonController, you can get how it is called by:
// jsonController.js
module.exports = (req, res) => {
let routePath = req.route.path;
if (routePath === '/readJson') {
res.send('From readJson');
} else if (routePath === '/readJson2') {
res.send('From readJson2');
}
};

Why promise.resolve wait forever in this case?

I am a nodejs's newbie. I'm testing a promise and have an issue.
Here's my issue.
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.get('/', async function(req,res){
console.log(222);
res.send("Hello!!!");
let check;
try {
console.log(3333);
check = await test();
console.log(4444);
} catch (err) {
console.log("Error : ", err);
}
console.log(111, check);
});
function test () {
return new Promise (resolve => {
console.log(5555);
app.get('/test', function(req, res) {
count = count + 1;
res.send(count.toString());
resolve("hahahaha");
})
})
}
app.listen(9000, function(){
console.log("hehehehe");
});
In a get 'http://localhost:9000' callback, I wait for 'http://localhost:9000/test' result to do something. The thing is, it's working fine for the first time. But since the 2nd, the promise.resolve() function doesn't work.
Here is my first time log:
hehehehe
222
3333
5555
4444
111 'hahahaha'
And here is my second time log :
222
3333
5555
the promise.resovle() doesn't work. It's waiting forever and I don't understand.
EDIT : Here is the solution for using EventEmitter to do signup and smsVerifyCode after modified by the help of Mr. #Aritra Chakraborty
var express = require('express');
var userControler = require('../Controler/user');
var router = express.Router();
var utils = require('../Helper/Utils');
var user_model = require('../Models/user');
const TIMEOUT_VERIFY = 300000;
const CODE_EXPIRED = 0;
const CODE_VALID = 1;
const CODE_INVALID = 2;
const CONTACT_EXISTED = 3;
const DATABASE_ABUSED = 4;
const events = require('events');
const emitter = new events.EventEmitter();
function timeout_verify_sms_emitter (time) {
setTimeout(() => {
emitter.emit('timeout_sms');
}, time);
}
function verify_code(codeGen) {
return new Promise((resolve, reject)=>{
emitter.on("verifySMS", (data)=>{
if (data === codeGen) {
resolve(CODE_VALID);
}
else {
resolve(CODE_INVALID);
}
})
emitter.on('timeout_sms', () =>{
resolve(CODE_EXPIRED);
});
})
}
router.get('/',function(req,res){
res.send("Welcome to the Earth!!!");
})
router.post('/signup', async function(req,res){
let verifyCode;
let checkContact;
let codeGen = utils.generateCode();
try {
checkContact = await user_model.checkContact(userData.contact);
if (checkContact === true) {
res.send(CONTACT_EXISTED);
}
else {
//call send sms to contact function here
//exam : sendSMS(contact)
//
timeout_verify_sms_emitter(TIMEOUT_VERIFY);
verifyCode = await verify_code(codeGen);
}
}
catch (err) {
console.log("Error : ", err);
}
if (verifyCode === CODE_EXPIRED) {
res.send(CODE_EXPIRED);
}
else if (verifyCode === CODE_VALID) {
var result = userControler.processUserData(req.body);
if (result) {
res.send(CODE_VALID);
}
else {
res.send(DATABASE_ABUSED);
}
}
else {
res.send (CODE_INVALID);
}
})
router.post('/signup/verifySMS', function(req, res){
emitter.emit("verifySMS", req.body.smsCode);
})
module.exports = router;
According to the above code:
Whenever you do a get request to / you are CREATING a /test path.
So, the first time it works because /test path has one handler.
Second or more time it doesn't works because,
The /test route has multiple handler now.
How express works is, routes get executed according to their declaration time. (Think middlewares)
Now, Second time the /test will have 2 handlers. And when you hit /test the first handler runs. And as this is not a middlware it doesn't go to the next handler. Now, the first handler has a different resolve function then the second one. So the second resolve function doesn't run at all.(Think closure)
For what are you trying to do most web implementations use long polling. Because if you wait too long for the second route it will throw a timeout error. Means you periodically hit an api to get the status of something. Means you create 3 routes.
A main route, like /signup
A second route like /sendsms
A third route where you send a particual identifier and it returns some positve/negative value. like /sendsms/check, where you might pass the phone number.
Otherwise if you don't care about timeouts you can use EventEmitter inside the /test route.
EDIT1:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json());
const events = require('events');
const emitter = new events.EventEmitter();
let count = 0;
app.get('/', async function (req, res) {
console.log(222);
res.send("Hello!!!");
let check;
try {
console.log(3333);
check = await test();
console.log(4444);
}
catch (err) {
console.log("Error : ", err);
}
console.log(111, check);
});
app.get('/test', function (req, res) {
count = count + 1;
emitter.emit("test",count.toString());
res.send(count.toString());
})
function test(){
return new Promise((res)=>{
emitter.on("test", (data)=>{
res(data);
})
})
}
app.listen(9000, function () {
console.log("hehehehe");
});
EDIT2:
Regarding the solution, you need to handle the timeout differently. Let's say your timeout is 3sec. And the SMS route took 100sec to get a response or maybe it didn't even got a response. Then your function will be stuck there.
function test(sendSMSTime) {
return new Promise((res, rej) => {
emitter.on("test", (data) => {
.
.
res(data);
})
emitter.on('timeout', rej);//On timeout it will run.
})
}
function timeoutEmitter(timeout) {
setTimeout(() => {
emitter.emit('timeout');
}, timeout)
}
app.post('/signup', async function (req, res) {
try {
timeoutEmitter(3000);
.
.
}catch{
}
});

node - continuation-local-storage

I am attempting to use the continuation-local-storage package to access the current express request/response from a point where that is not readily accessible.
I created the following middleware:
var createNamespace = require('continuation-local-storage').createNamespace,
getNamespace = require('continuation-local-storage').getNamespace;
const domain = 'ns.cls';
exports.configure = function(app) {
createNamespace(domain);
app.use(function(req, res, next) {
exports.set(req, res, "callcontext", { req, res });
next();
});
};
exports.set = function(req, res, name, value) {
var namespace = getNamespace(domain);
namespace.bindEmitter(req);
namespace.bindEmitter(res);
namespace.run(() => namespace.set(name, value));
};
exports.get = function(name) {
var namespace = getNamespace(domain);
return namespace.get(name);
};
exports.getCallContext = function() {
return exports.get("callcontext");
};
However when I attempt to access the context it is undefined:
var localStorage = require('../middleware/local-storage');
module.exports = function(doc, ctx) {
var callContext = localStorage.getCallContext();
console.log("value: " + callContext);
};
Does anyone have any ideas?
Thanks in advance,
Mark
createNameSpace should be called once. Also, you have an error on line
exports.set(req, res, "callcontext", { req, res });
should be something like
exports.set(req, res, "callcontext", { key: value });
This is the way I am using it:
to set
var session = require('continuation-local-storage').createNamespace('session')
app.use(function(req, res, next) {
session.bindEmitter(req);
session.bindEmitter(res);
session.run(function() {
session.set('req', req);
next();
});
});
to get
var session = require('continuation-local-storage').getNamespace('session')
session.get('req')

Resources