i have a problem or not even a problem just not enough knowledge about this, so the question is simple, i have code
router.get('/', (ctx, next) => {
MongoClient.connect(url, {useNewUrlParser: true}, function (err, db) {
if (err) throw err;
let dbo = db.db("mydb");
let query = {address: "Highway 37"};
dbo.collection("customers").find(query).toArray((err, result) => {
if (err) throw err;
console.log(result)
db.close();
});
});
ctx.body = 'END OF FILE!!!';
});
console.log(result) i have my data and i need to response this data in ctx.body and i don;t know how to get result to my ctx.body, i am trying some options like create a variable and like let a, and a = result etc, however all hope is gone :)
Please any help will be appreciated, tnx a lot ^)
Your handler could look like this:
router.get('/', ctx => {
MongoClient.connect(..., (err, db) => {
...
dbo.collection("customers").find(query).toArray((err, result) => {
ctx.body = JSON.stringify(result)
})
})
})
Related
I use a sqlite3 database for a node.js express. If I return the request as in the tutorial in router.js it works and I get all the items. Now I have created a service to get the sql from the route (controller). But unfortunately I don't get anything back. I had already tried it with async await in the service. That didn't help either.
my code:
// router.js
const dbService = require("../services/dbService/");
router.get("/users", (req, res, next) => {
try {
res.status(200).send({
data: dbService.getAllUsers();
})
return;
} catch(err) {
next(err);
}
});
// dbService.js
const db = require("../db/database.js");
module.exports = {
getAllUsers() {
const sql = "select * from users";
db.all(sql,[], (err, rows) => {
return {"data": rows};
});
}
}
For simple reasons, I have not included error handling in the code. Why can't I get database values from the service? What do I have to do?
Thanks in advance! Mike
You're running afoul of asynchronous JS. db.all returns results to the callback.
A refactor to use callbacks would look something like:
// router.js
const dbService = require("../services/dbService/");
router.get("/users", (req, res, next) => {
dbService.getAllUsers((err, result) => {
if (err) next(err);
res.json({
data: result;
});
});
});
// dbService.js
const db = require("../db/database.js");
module.exports = {
getAllUsers(cb) {
const sql = "select * from users";
db.all(sql,[], (err, rows) => {
cb(err, rows);
});
}
}
And promises woudl look like:
// router.js
const dbService = require("../services/dbService/");
router.get("/users", async (req, res, next) => {
try {
const result = await dbService.getAllUsers();
res.json({
data: result;
});
} catch (err) {
next(err);
}
});
// dbService.js
const db = require("../db/database.js");
module.exports = {
getAllUsers(cb) {
const sql = "select * from users";
return new Promise((resolve, reject) =>
db.all(sql,[], (err, rows) => {
if (err) reject(err);
resolve(rows);
})
);
}
}
I have a task that requires me to delete some data in an array that is in a JSON file, using node/express. I want, when a delete request is made, to delete a specific item that matches a specific id in the array that is in the JSON file. I tried using the filter method, but it doesn't seem to work.
JS file:
var obj = { projects: []};
app.post('/', (req, res, next)=>{
let identifier = req.query.identify; //id of project
fs.readFile('webProjects.json', (err, data)=>{
if(err) throw err;
obj = JSON.parse(data);
obj.projects.push({id:identifier, game: req.query.project});
let json = JSON.stringify(obj);
fs.writeFile('webProjects.json', json, (err)=>{
if(err) throw err
console.log("updatedd")
})
})
})
/*when user sends delete request, delete specific data.*/
app.delete("/", (req, res, next)=>{
fs.readFile('webProjects.json', (err, data)=>{
console.log(data)
obj = JSON.parse(data);
obj.projects.filter((item)=>{
let url = req.query.identify;
return item.id !== url;
})
console.log(obj)
let json = JSON.stringify(obj);
fs.writeFile('webProjects.json', json, (err)=>{
if(err) throw err;
console.log(obj)
})
})
})
/*when user navigates to another page, we display the data of the resource*/
app.get('/:id', (req, res, next)=>{
fs.readFile('webProjects.json', (err, data)=>{
if (err) throw err
res.send(data);
})
})
/*we want to catch all errors, with the requests made to the server.
used the wildcard(*) to make sure that we catch all requests made to the server.
*/
app.get('*', (req, res, next)=>{
let err = new Error('There was an error in accessing the page you wanted');
err.statusCode = 404;
next(err);
})
app.use((err, req, res, next)=>{
console.log(err.message)
if(!err.statusCode) err.statusCode = 500;
res.status(err.statusCode).send(err.message);
})
app.listen(8080, ()=>{
console.log("server has listened")
})
JSON file/data:
{"projects":[{"id":"1","game":"miniGame"},{"id":"2","game":"min"}]}
The filter function does not change the array so you need to assign the filtered items back to the array.
fs.readFile('webProjects.json', (err, data)=>{
console.log(data)
obj = JSON.parse(data);
// assign the filtered array back to the original array
obj.projects = obj.projects.filter((item)=>{
let url = req.query.identify;
return item.id !== url;
})
console.log(obj)
let json = JSON.stringify(obj);
fs.writeFile('webProjects.json', json, (err)=>{
if(err) throw err;
console.log(obj)
})
})
I am using normal http request for deleting value from mysql database using node.js. But right now, only values are deleted statically not dynamically. I want to delete the data dynamically by providing the id.
const server = http.createServer();
const reqUrl = url.parse(req.url, true);
server.on('request', (req, res) => {
if (reqUrl.pathname === '/delete'){
req.on('end', () => {
let sql = "Delete from students where id=12";
connection.query(sql, function (err, result) {
if (err) throw err;
console.log(result);
});
})
res.end();
}
});
now, after running this code localhost:3000/delete only the id=12 is deleted all time. But I want to do this localhost:3000/delete?id=12 giving input values as id.
I tried to give sql command as "Delete from students where id=?" , but it gave errors. How can I solve this?
That should be simple.
You just need to receive the param from your request and append it to string.
Here's your updated code.
server.on('request', (req, res) => {
if (reqUrl.pathname === '/delete'){
req.on('end', () => {
let studid = req.query.id; //Get the student id
let sql = "Delete from students where id="+studid; //append it to query
connection.query(sql, function (err, result) {
if (err) throw err;
console.log(result);
});
})
res.end();
}
});
I'm working with PostgreSQL and NodeJS with its "PG Module".
CRUD works but sometimes doesn't update automatically the views when i save or delete some item. this is my code and I think that the error is here but i cannot find it, i tried everything :'(
Error Message:
const controller = {};
const { Pool } = require('pg');
var connectionString = 'postgres://me:system#localhost/recipebookdb';
const pool = new Pool({
connectionString: connectionString,
})
controller.list = (request, response) => {
pool.query('SELECT * FROM recipes', (err, result) => {
if (err) {
return next(err);
}
return response.render('recipes', { data: result.rows });
});
};
controller.save = (req, res) => {
pool.query('INSERT INTO recipes(name, ingredients, directions) VALUES ($1, $2, $3)',
[req.body.name, req.body.ingredients, req.body.directions]);
return res.redirect('/');
};
controller.delete = (req, res) => {
pool.query('DELETE FROM RECIPES WHERE ID = $1', [req.params.id]);
return res.redirect('/');
}
module.exports = controller;
PD: CRUD works but sometimes appears that error.
This error occurs when you sent a response before and then you try to send response again. For this you have to check if there is any piece of code that is sending your response twice. Sometimes it happens due to asynchronous behavior of nodejs. Sometimes a process will be in event loop and we send response and when it finishes execution response will be sent again. So You can use callbacks or async await to wait for execution.
Callback
const controller = {};
const { Pool } = require('pg');
var connectionString = 'postgres://me:system#localhost/recipebookdb';
const pool = new Pool({
connectionString: connectionString,
})
controller.list = (request, response) => {
pool.query('SELECT * FROM recipes', (err, result) => {
if (err) {
return next(err);
}
return response.render('recipes', { data: result.rows });
});
};
controller.save = (req, res) => {
pool.query('INSERT INTO recipes(name, ingredients, directions) VALUES ($1, $2,$3)',
[req.body.name, req.body.ingredients, req.body.directions],function(err,resp)
{
if(err){
console.log(err)
}else{
return res.redirect('/');
}
});
};
controller.delete = (req, res) => {
pool.query('DELETE FROM RECIPES WHERE ID = $1', [req.params.id],function(err,resp){
if(err){
console.log(err)
}else{
return res.redirect('/');
}
});
}
module.exports = controller;
Or You can also use async await to wait for execution and then send response.
Async/Await
const controller = {};
const { Pool } = require('pg');
var connectionString = 'postgres://me:system#localhost/recipebookdb';
const pool = new Pool({
connectionString: connectionString,
})
controller.list = async(request, response) => {
try{
const result = await pool.query('SELECT * FROM recipes');
return response.render('recipes', { data: result.rows });
}
catch(err){
return next(err);
}
};
controller.save = async(req, res) => {
try{
await pool.query('INSERT INTO recipes(name, ingredients, directions) VALUES ($1, $2,$3)',[req.body.name, req.body.ingredients, req.body.directions]);
return res.redirect('/');
}
catch(err){
return next(err);
}
};
controller.delete = async(req, res) => {
try{
await pool.query('DELETE FROM RECIPES WHERE ID = $1', [req.params.id]);
return res.redirect('/');
}catch(err){
console.log(err);
}
}
module.exports = controller;
Check res.send() should not call two times.
In Controller
const getAll = function(req, res){
res.send(service.getAll(req,res));
}
In Service
const Type = require("../models/type.model.js");
exports.getAll = (req, res) => {
Type.getAll((err, data) => {
res.send(data);
});
};
Above res.send(data); two-time calling will create a problem. better to use
const getAll = function(req, res){
service.getAll(req,res);
}
You need to embed your response in the callback to the query. Since the call is asynchronous, sending the response earlier will terminate the call stack never waiting for the webapi(Behaviour may vary).
controller.delete = (req, res) => {
pool.query('DELETE FROM RECIPES WHERE ID = $1', [req.params.id],(err, result)
=> {
// error handling can be done accordingly
return res.redirect('/');
})
}
I want to read out a mongodb database with API URLS. When I access /showdb in my browser the json is only display after the second refresh. How can I get it the first time? Thanks!
const express = require("express");
const app = express();
var mongo = require('mongodb');
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
var resultdb;
function readDB() {
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db("simpledb");
dbo.collection("simplecollection").find().toArray(function(err, result) {
if (err) throw err;
resultdb = result;
db.close();
});
});
return resultdb;
};
//handle normal file requests etc.
app.use(express.static(__dirname + "/"));
app.get('/showdb', function(req, res) {
res.send(readDB());
});
app.listen(10008);
console.log("Server running on port: " + 10008);
What happens here is that you return resultdb without awaiting the db response. Hence why second call works due to your variable is getting updated after res has been sent. Try below
const url = "mongodb://localhost:27017/";
const mongoClient = new MongoClient(new Server(url, 27017));
async function readDB() {
mongoClient.open(function(err, db) {
if (err) throw err;
var dbo = db.db("simpledb");
const res = dbo.collection("simplecollection").find().toArray(function(err, result) {
if (err) throw err;
return result
});
mongoClient.close();
return await res
});
};
mongoClient.open(function(err, mongoClient) {
var db1 = mongoClient.db("mydb");
mongoClient.close();
});
Also, it's not a good practice to create connection for every task.
I would suggest to create a separate function to connect upon server start & then just use client.open() when you want to do db tasks
You need to use the callbacks you can't use synchronous code. Like this:
app.get('/', (req, res) => {
MongoClient.connect(url, (conn, err) => {
conn.db('foo').collection('bar').find().toArray((err, result) => {
res.send(result)
})
})
})
The callback functions are executed later that's why they are callbacks. If you want to write code that looks more like synchronous code look at promise API and await
The problem with code is that it does not wait for readDB() to finish it tasks with Mongodb and returns with empty as resultdb is just defined.
But when you call it once, after the request is served, readDB() would have received data from Mongodb and it will be set to resultdb. Next time when you call the api, you get the result processed in the previous api call and not the new one.
Try this -
app.get('/showdb', async function(req, res) {
const result = await readDB(); // here we are waiting for the results to finish using await.
res.send(result);
});
and your readDB function as -
async function readDB() { // making using of async here.
MongoClient.connect(url, function(err, db) {
if (err) throw err;
const dbo = db.db('simpledb');
dbo.collection('simplecollection').find().toArray(function(err, result) {
if (err) throw err;
resultdb = result;
return resultdb; // we can now return it.
db.close();
});
});
};
Note: Considering you're using an updated Node version with support for async - await
--- UPDATE ----
You can try this -
app.get('/showdb', async function(req, res) {
readDB(req, res);
});
function readDB(req, res) { // making using of async here.
MongoClient.connect(url, function(err, db) {
if (err){
res.send(err);
throw err;
}
const dbo = db.db('simpledb');
dbo.collection('simplecollection').find().toArray(function(err, result) {
if (err){
res.send(err);
throw err;
}
res.send(result)
db.close();
});
});
};