incorrect response in angular - node.js

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);

Related

Promise.all returning undefined in Node JS

I have a code to fetch directory names from first API. For every directory, need to get the file name from a second API. I am using something like this in my Node JS code -
async function main_function(req, res) {
const response = await fetch(...)
.then((response) => {
if (response.ok) {
return response.text();
} else {
return "";
}
})
.then((data) => {
dirs = ...some logic to extract number of directories...
const tempPromises = [];
for (i = 0; i < dirs.length; i++) {
tempPromises.push(getFilename(i));
}
console.log(tempPromises); // Prints [ Promise { <pending> } ]
Promise.all(tempPromises).then((result_new) => {
console.log(result_new); // This prints "undefined"
res.send({ status: "ok" });
});
});
}
async function getFilename(inp_a) {
const response = await fetch(...)
.then((response) => {
if (response.ok) {
return response.text();
} else {
return "";
}
})
.then((data) => {
return new Promise((resolve) => {
resolve("Temp Name");
});
});
}
What am I missing here?
Your getFilename() doesn't seem to be returning anything i.e it's returning undefined. Try returning response at the end of the function,
async function getFilename(inp_a) {
const response = ...
return response;
}
Thanks to Mat J for the comment. I was able to simplify my code and also learn when no to use chaining.
Also thanks to Shadab's answer which helped me know that async function always returns a promise and it was that default promise being returned and not the actual string. Wasn't aware of that. (I am pretty new to JS)
Here's my final code/logic which works -
async function main_function(req,res){
try{
const response = await fetch(...)
const resp = await response.text();
dirs = ...some logic to extract number of directories...
const tempPromises = [];
for (i = 0; i < dirs.length; i++) {
tempPromises.push(getFilename(i));
}
Promise.all(tempPromises).then((result_new) => {
console.log(result_new);
res.send({ status: "ok" });
});
}
catch(err){
console.log(err)
res.send({"status" : "error"})
}
}
async function getFilename(inp_a) {
const response = await fetch(...)
respText = await response.text();
return("Temp Name"); //
}

Asynchronicity issue: why does the second part of my function run before a loop event finishes?

I have a route on an Express server that updates a User profile. The User profile is updated before I have finished to parse the data to update. How so?
I want to update two const: newProfilePicture & newOtherPictures. They are correctly updated, but after the user has been updated, so it's useless. How to fix this asynchronicity issue?
Here is the function:
router.post("/upload-images", upload.array("image"), async (req, res) => {
const { userId } = req.body;
try {
if (req.files) {
let newProfilePicture = null;
let newOtherPictures = [];
req.files.forEach(({ path, originalname }) => {
cloudinary.uploader.upload(
path,
{
resource_type: "image",
public_id: `myapp/users/${userId}/${originalname}`,
crop: "scale",
quality: "auto",
},
(err, res) => {
if (err) {
return fs.unlinkSync("./" + path);
}
fs.unlinkSync("./" + path);
if (originalname === "main") {
return (newProfilePicture = res.secure_url);
}
return newOtherPictures.push({
id: originalname,
url: res.secure_url,
});
}
);
});
// THIS PART IS COMPLETE BEFORE THE req.files.forEach IS DONE
const user = await User.findById(userId);
const { otherPictures, profilePicture } = updatePictures(
newProfilePicture,
newOtherPictures,
user
);
User.findByIdAndUpdate(
userId,
{ profilePicture, otherPictures },
{ new: true }
);
res.send("upload images success");
}
} catch (err) {
console.log("err", err);
return res.status(500).send("upload images failed");
}
});
It happens because cloudinary.uploader.upload() runs asynchronously. Since you mentioned it doesn't have promise interface, you can convert the callback to promise using NodeJS's util.promise function as it's error first callback.
const { promisify } = require("util");
const fs = require("fs");
const cloudinaryUpload = promisify(cloudinary.uploader.upload.bind(cloudinary.uploader))
router.post("/upload-images", upload.array("image"), async (req, res) => {
try {
if (!req.files) {
return res.send("no images in the request body");
}
let newProfilePicture = null;
let newOtherPictures = [];
for (const { path, originalName } of req.files) {
try {
const response = await cloudinaryUpload(path, {
resource_type: "image",
public_id: `myapp/users/${userId}/${originalName}`,
crop: "scale",
quality: "auto",
});
await fs.promises.unlink("./" + path);
if (originalname === "main") {
newProfilePicture = response.secure_url;
continue;
}
newOtherPictures.push({
id: originalName,
url: response.secure_url,
});
} catch (error) {
//do what you want if there is an error
//throw error if you want
await fs.promises.unlink("./" + path);
}
}
const user = await User.findById(userId);
const { otherPictures, profilePicture } = updatePictures(
newProfilePicture,
newOtherPictures,
user
);
//use User.updateOne() as you don't need the doc back
await User.findByIdAndUpdate(
userId,
{ profilePicture, otherPictures },
{ new: true }
);
return res.send("upload images success");
} catch (error) {
console.log("err", err);
return res.status(500).send("upload images failed");
}
});

How to read `JSON` object in Angular

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;
});
}

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

Mongodb not updating the data after put request returns successful

In trying to use the objectid in the mongoose schema as a reference to do a put to update a document in a collection. The console logs its as a success but when I refresh the page or look in the mongo shell nothing changes.
Heres the put in the expressjs router:
router.put('/messageupdate/:empId', function (req, res) {
var values = req.body;
console.log(values);
var empId = req.params.empId;
console.log(empId);
Message.update({empId: empId}, values, function(err, values) {
if (!err) {
res.json("okay");
} else {
res.write("fail");
}
});
})
Heres the service method:
updateServiceWithId(message: Message): Observable<any> {
console.log(message);
const body = JSON.stringify(message);
console.log(body);
const headers = new Headers({'Content-Type': 'application/json'});
return this.http.put('http://localhost:3000/messageupdate/:empId', body, {headers: headers});
}
Heres the client side method that triggers the put:
onUpdateMessage() {
var retVal = confirm("Do you want to continue ?");
if( retVal == true ){
const message = new Message(this.fname,this.lname,this.empId,this.number,this.occu);
console.log(this.fname);console.log(this.lname);
console.log(this.empId);console.log(this.occu);
this.messages.push(message);
this.messageService.updateServiceWithId(message)
.subscribe(
() => console.log('Success!'),
error => console.error(error)
);
}
else{
alert("Edit cancled!");
return false;
}
}

Resources