How to read `JSON` object in Angular - node.js

I have a API in my Node app like this:
exports.getPlanningStages = async (req, res, next) => {
const currentPage = req.query.page || 1;
const perPage = 10;
try {
const totalItems = await Planningstage.find().countDocuments();
const planningstages = await Planningstage.find()
.populate("creator")
.sort({ createdAt: -1 })
.skip((currentPage - 1) * perPage)
.limit(perPage);
// res.status(200).json(planningstages);
res.status(200).json({
planningstages,
totalItems: totalItems,
});
} catch (err) {
if (!err.statusCode) {
err.statusCode = 500;
}
next(err);
}
};
And this is my HTTP request in Angular:
fetch() {
this.psService.getPlanningStages().subscribe((resData) => {
console.log(resData);
});
}
This is the response of my request: console.log
How can I split this json into two separate variables?

Try using ES6 Destructuring assignment feature like this:
fetch() {
this.psService.getPlanningStages().subscribe((resData) => {
const [planningstages, totalitems] = resData;
});
}

Related

Fastifyis not defined and fastify-postgres Fastify.pg.connect not working

I have defined my fastify like so:
const fastify = require('fastify')({logger: true})
fastify
.register(require('./setup/envs'))
.after(async (err) => {
if (err) console.log(err);
fastify.register(require('./setup/db'))
await fastify.after()
fastify.register(require('./setup/jwt'))
await fastify.after()
fastify.register(require('./setup/auth'))
await fastify.after()
// load routes
// fastify.register(require('./routes/test'))
fastify.register(require('./routes/posts/index'), { prefix: '/posts' })
})
const start = async () => {
try {
await fastify.ready()
fastify.listen(3000)
} catch (e) {
fastify.log.error(e)
process.exit(1)
}
}
start();
Now in my post routes, I have the following:
const postRoutes = require('../../controllers/posts');
async function PostRoutes(fastify, options) {
fastify.addHook('preValidation', fastify.verifyJWT)
fastify.addHook('preHandler', function (req, reply, done) {
if (req.body) {
req.log.info({ body: req.body }, 'parsed body')
}
if (req.params) {
req.log.info({ params: req.body }, 'parsed params')
}
done()
})
// get all posts
fastify.get('/:limit/:page', postRoutes.getPosts)
fastify.post('/signup', async (req, reply) => {
// some code
const token = fastify.jwt.sign({ test: 'hello' })
reply.send({ token })
})
fastify.get(
"/test-auth",
async function(request, reply) {
return { test: 'auth' }
}
)
}
module.exports = PostRoutes;
and my controller file is the following:
const fastify = require('fastify');
const getPosts = async (req, reply) => {
try {
const client = await fastify.pg.connect()
const { rows } = await client.query(
'SELECT * FROM POSTS LIMIT $1 OFFSET $2;', [req.params.limit, req.params.offset],
)
client.release()
return rows
} catch (e) {
req.log.error('Getting posts failed with params')
throw new Error(e)
}
}
module.exports = {
getPosts,
};
The const client = await fastify.pg.connect() is giving me fastify is not defined and if I require it by adding const fastify = require('fastify') at the top, I get TypeError: Cannot read properties of undefined (reading 'connect').
the following is my db.js:
const fastifyPlugin = require('fastify-plugin');
const fastifyPostgres = require('fastify-postgres');
async function dbConnector (fastify, options) {
const dbUser = encodeURIComponent(fastify.config.DATABASE_USERNAME)
const dbPassword = encodeURIComponent(fastify.config.DATABASE_PASSWORD);
const dbHost = encodeURIComponent(process.env.DATABASE_HOST);
const dbName = encodeURIComponent(fastify.config.DATABASE_NAME);
fastify.register(fastifyPostgres, {
connectionString: `postgres://${dbUser}:${dbPassword}#${dbHost}/${dbName}`
})
}
// Wrapping a plugin function with fastify-plugin exposes the decorators
// and hooks, declared inside the plugin to the parent scope.
module.exports = fastifyPlugin(dbConnector);
I had to change my route to
fastify.get('/:limit/:page', (req, reply) => postRoutes.getPosts(fastify, req, reply))
and then I was able to access the fastify object in my controller.

incorrect response in angular

i'm new at nodejs & angular
here is my restAPI function :
exports.getPlanningStages = async (req, res, next) => {
const currentPage = req.query.page || 1;
const perPage = 2;
try {
const totalItems = await Planningstage.find().countDocuments();
const planningstages = await Planningstage.find()
.populate('creator')
.sort({ createdAt: -1 })
.skip((currentPage - 1) * perPage)
.limit(perPage);
res.status(200).json({
planningstages
});
} catch (err) {
if (!err.statusCode) {
err.statusCode = 500;
}
next(err);
}
};
at the console i see the correct response json array
the angular code is
planningstage.service.ts
private ps: Planningstage[] = [];
getPlanningStages() {
return this.httpService
.get<Planningstage[]>(
"http://localhost:8080/planningstage/getPlanningStage"
);
}
planningstage.component.ts
ngOnInit() {
this.fetch();
}
fetch() {
this.psService.getPlanningStages().subscribe(resData => {
console.log(resData);
});
the response at the browser
browser response
how can i read the currect response at my angular code
thank's
It seems your problem is with this line,
res.status(200).json({
planningstages
});
instead of above line, make like this
res.status(200).json(planningstages);

Error: connect ECONNREFUSED 127.0.0.1:5000

I´ve the file cases.js to create the route I want:
const express = require("express");
const { requireSignin } = require("../controllers/auth");
const { getCases } = require("../controllers/cases");
const { scrapingData } = require("../scrapingData");
const router = express.Router();
router.get("/cases", requireSignin, scrapingData, getCases);
module.exports = router;
requireSignin from controllers/auth looks like this:
exports.requireSignin = expressJwt({
secret: process.env.JWT_SECRET,
userProperty: "auth",
});
scrapingData as middleware I have:
const updateMongoRecords = async () => {
mongoose.Promise = global.Promise;
mongoose.set("debug", true);
Case.deleteMany({}, (err, result) => {
if (err) {
console.log(err);
} else {
console.log("Successfully deleted all records");
}
});
const dataPath = Path.join(__dirname, "files", "covid-data.csv");
try {
let headers = Object.keys(Case.schema.paths).filter(
(k) => ["_id", "__v"].indexOf(k) === -1
);
await new Promise((resolve, reject) => {
let buffer = [],
counter = 0;
let stream = fs
.createReadStream(dataPath)
.pipe(csv())
.on("error", reject)
.on("data", async (doc) => {
stream.pause();
buffer.push(doc);
counter++;
// log(doc);
try {
if (counter > 10000) {
await Case.insertMany(buffer);
buffer = [];
counter = 0;
}
} catch (e) {
stream.destroy(e);
}
stream.resume();
})
.on("end", async () => {
try {
if (counter > 0) {
await Case.insertMany(buffer);
buffer = [];
counter = 0;
resolve();
}
} catch (e) {
stream.destroy(e);
}
});
});
} catch (e) {
console.error(e);
} finally {
process.exit();
}
};
exports.scrapingData = async (req, res, next) => {
const url = "https://covid.ourworldindata.org/data/owid-covid-data.csv";
const path = Path.resolve(__dirname, "files", "covid-data.csv");
const response = await Axios({
method: "GET",
url: url,
responseType: "stream",
});
response.data.pipe(fs.createWriteStream(path));
return new Promise((resolve, reject) => {
response.data.on("end", () => {
resolve(updateMongoRecords());
next();
});
response.data.on("error", (err) => {
reject(err);
});
});
};
And getCases.js inside controllers/cases I have:
const Case = require("../models/case");
exports.getCases = async (req, res) => {
const cases = await Case.find().then((cases) => res.json(cases));
};
With this code I am able to fetch in the route /cases all the cases in the client side (like postman) and it shows all of them. But the problem is that I can´t make any other requests (like signing out, which works fine if I don´t make the get request for the cases like before) afterwards because client (postman) gives the error: GET http://localhost:5000/signout
Error: connect ECONNREFUSED 127.0.0.1:5000
in case you want to see the code for signout is like this:
const express = require("express");
const { signup, signin, signout } = require("../controllers/auth");
const router = express.Router();
router.post("/signup", userSignupValidator, signup);
router.post("/signin", userSigninValidator, signin);
router.get("/signout", signout);
inside controllers/auth.js:
exports.signout = (req, res) => {
res.clearCookie("t");
return res.json({ message: "Signout successfully done" });
};
Any help on this??

How to consume a RESTful API in Node.js

I'm new to Node.js and I'm creating a simple pagination page. The REST API works fine, but consuming it has left me in limbo.
Here is the REST API (other parts have been taken out for brevity)
const data = req.query.pageNo;
const pageNo =
(typeof data === 'undefined' || data < 1) ? 1 : parseInt(req.query.pageNo);
let query = {};
const total = 10;
query.skip = (total * pageNo) - total;
query.limit = total;
try {
const totalCount = await Users.countDocuments();
const pageTotal = Math.ceil(totalCount / total);
const users = await Users.find({}, {}, query);
return res.status(200).json(users);
} catch (error) {
console.log('Error ', error);
return res.status(400).send(error)
};
};
When I return the json with just the 'users' object, like so return res.status(200).json(users); the page renders correctly, but when I pass in other objects like what I have in the code, it fails. This is how I'm consuming the API:
const renderHomepage = (req, res, responseBody) => {
let message = null;
if (!(responseBody instanceof Array)) {
message = 'API lookup error';
responseBody = [];
} else {
if (!responseBody.length) {
message = 'No users found nearby';
}
}
res.render('users-list', {
title: 'Home Page',
users: responseBody,
message: message
});
}
const homelist = (req, res) => {
const path = '/api/users';
const requestOptions = {
url: `${apiOptions.server}${path}`,
method: 'GET',
json: true,
};
request(
requestOptions,
(err, {statusCode}, body) => {
if (err) {
console.log('Ther was an error ', err);
} else if (statusCode === 200 && body.length) {
renderHomepage(req, res, body);
} else if (statusCode !== 200 && !body.length) {
console.log('error ',statusCode);
}
}
);
}
I've searched extensively on both here and other resources but none of the solutions quite answers my question. I hope someone could be of help

koa2+koa-router+mysql keep returning 'Not Found'

Background
I am using koa2 with some middlewares to build a basic api framework. But when I use "ctx.body" to send response in my router, the client side always receive "Not Found"
My code
./app.js
const Koa = require('koa');
const app = new Koa();
const config = require('./config');
//Middlewares
const loggerAsync = require('./middleware/logger-async')
const bodyParser = require('koa-bodyparser')
const jsonp = require('koa-jsonp')
app.use(loggerAsync())
app.use(bodyParser())
app.use(jsonp());
//Router
const gateway = require('./router/gateway')
app.use(gateway.routes(), gateway.allowedMethods());
app.use(async(ctx, next) => {
await next();
ctx.response.body = {
success: false,
code: config.code_system,
message: 'wrong path'
}
});
app.listen(3000);
./router/gateway.js
/**
* Created by Administrator on 2017/4/11.
*/
const Router = require('koa-router');
const gateway = new Router();
const df = require('../db/data-fetcher');
const config = require('../config');
const moment = require('moment');
const log4js = require('log4js');
// log4js.configure({
// appenders: { cheese: { type: 'file', filename: 'cheese.log' } },
// categories: { default: { appenders: ['cheese'], level: 'error' } }
// });
const logger = log4js.getLogger('cheese');
logger.setLevel('ERROR');
gateway.get('/gateway', async(ctx, next) => {
let time = ctx.query.time;
if (!time) {
ctx.body = {
success: false,
code: config.code_system,
message: 'Please input running times'
}
} else {
try {
let r = await df(`insert into gateway (g_time, g_result, g_date) values (${time}, '',now())`);
return ctx.body = {
success: true,
code: config.code_success
}
} catch (error) {
logger.error(error.message);
}
}
});
module.exports = gateway;
Then a db wrapper(mysql)
./db/async-db.js
const mysql = require('mysql');
const config = require('../config');
const pool = mysql.createPool({
host: config.database.HOST,
user: config.database.USERNAME,
password: config.database.PASSWORD,
database: config.database.DATABASE
})
let query = (sql, values) => {
return new Promise((resolve, reject) => {
pool.getConnection(function (err, connection) {
if (err) {
reject(err)
} else {
connection.query(sql, values, (err, rows) => {
if (err) {
reject(err)
} else {
resolve(rows)
}
connection.release()
})
}
})
})
}
module.exports = query
./db/data-fetcher.js
const query = require('./async-db')
async function performQuery(sql) {
let dataList = await query(sql)
return dataList
}
module.exports = performQuery;
My running result
When I launch server on port 3000 then accesss via http://localhost:3000/gateway?time=5, it always returns "Not found". But as I can see I have already used
return ctx.body = {
success: true,
code: config.code_success
}
to send response. I debugged and found that the database processing was done well, the new data was inserted well.
when I remove that db inserting line, it works well and returns success info.
let r = await df(`insert into gateway (g_time, g_result, g_date) values (${time}, '',now())`);
Is there anything wrong?
Thanks a lot!
Update 2017/04/27
Now I have found the problem. It's due to my custom middleware
const loggerAsync = require('./middleware/logger-async')
Code are like following -
function log( ctx ) {
console.log( ctx.method, ctx.header.host + ctx.url )
}
module.exports = function () {
return function ( ctx, next ) {
return new Promise( ( resolve, reject ) => {
// 执行中间件的操作
log( ctx )
resolve()
return next()
}).catch(( err ) => {
return next()
})
}
}
I changed it to async/await way then everything is working well.
Could anyone please tell me what's wrong with this middleware?
I guess, your problem is the ./db/data-fetcher.js function. When you are calling
let r = await df(`insert ....`)
your df - function should return a promise.
So try to rewrite your ./db/data-fetcher.js like this (not tested):
const query = require('./async-db')
function performQuery(sql) {
return new Promise((resolve, reject) => {
query(sql).then(
result => {
resolve(result)
}
)
}
}
module.exports = performQuery;
Hope that helps.
correct middleware:
function log( ctx ) {
console.log( ctx.method, ctx.header.host + ctx.url )
}
module.exports = function () {
return function ( ctx, next ) {
log( ctx );
return next()
}
}
reason: when resolve involved; promise chain was completed; response has been sent to client. although middleware remained will involved, but response has gone!
try to understand It seems that if you want to use a common function as middleware, you have to return the next function
nodejs(koa):Can't set headers after they are sent

Resources