How to get respond from promise in JSON parse? - node.js

I'm trying to get response from API call in the JSON parse but do not see a way to get it.
I managed to get respond from promise but it's not usable because i need JSON parse respond (JSON.stringlify worked but also not usable) .
let Admins = scope.api.getChatAdministrators(scope.message._chat._id)
console.log(Admins);
Admins.then(function(result) {
console.log(result);
}) // Why this work?(I get this respond from it)
Respond:
[ ChatMember {
_user:
User {
_id: ID,
_firstName: 'AdminBot',
_lastName: null,
_username: 'Bot' },
_status: 'administrator' },
ChatMember {
_user:
User {
_id: ID,
_firstName: 'Creator',
_lastName: null,
_username: 'Creator' },
_status: 'creator' } ]
let Admins = scope.api.getChatAdministrators(scope.message._chat._id)
console.log(Admins);
Admins.then(function(result) {
console.log(JSON.parse(result));
}).catch((err) => {
console.log('API Call error:', err.message);
});
Tried this to get JSON parse output but i got response "API Call error: Unexpected token o in JSON at position 1"

This will look weird but this will do.
const temp = JSON.stringify(result)
const parsedResult = JSON.parse(temp)
FYI. you can only parse a JSON object in string format.

Related

Mongoose problem with object id "Cast to ObjectId failed for value"

It's along explanation so to make it easier I'll call users x and y.
I got this code, which the intention is to the X (making the requests) add his ID into Y's pending requests as well as his own sent requests.
const postSendBBRequest = async (req, res) => {
const userRecipient = await User.findById(req.params.id)
const userSender = await User.findById(req.userId);
const senderId = userSender.id;
try {
if (senderId == userRecipient.id) {
res.status(406).json("You cannot have yourself as a brother")
} else {
userSender.sentBBRequests.push({senderId});
await userSender.save();
userRecipient.receivedBBRequests.push({senderId});
await userRecipient.save();
res.status(201).json("Brotheband request sent sucessfully")
}
} catch (ERR) {
res.status(500).json({ Message: ERR.message });
}
}
My test route on Postman is /add/61b29bb33e775393ae369b79
The problem is: I'm getting an error: "Cast to ObjectId failed for value \"{ senderId: '61b29aef3e775393ae369b74' }\" (type Object) at path \"sentBBRequests\
I thought maybe the problem was how I organized my Schema too:
receivedBBRequests: [
{
type: mongoose.Schema.Types.ObjectId,
},
],
sentBBRequests: [
{
type: mongoose.Schema.Types.ObjectId,
},
],
brothers: {
type: [
{
type: mongoose.Schema.Types.ObjectId,
},
]}
There are too many points of failure I can't even come up with something to solve.
Thanks a lot.
You can use the following :
const senderId = userSender._id.toString();
const userRecipientId = userRecipient._id.toString();
this will allow you to convert the objectId to string

Why it only returns the first id from my mock up database?

In short I am trying to create a simple api that would return the user with the matching id. I use postman to send requests to my localhost created using node.js with express. It works fine when I request the first user but throws in an error when requesting "John". I am coding along a udemy course and can't figure out what the issue is other than the material is outdated. The error is "Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client"
users: [
{
id: "123",
name: "Sally",
email: "sally#gmail.com",
password: "bananas",
entries: 0,
joined: new Date(),
},
{
id: "124",
name: "John",
email: "john#gmail.com",
password: "apples",
entries: 0,
joined: new Date(),
},
],
};
app.get("/profile/:id", (req, res) => {
const { id } = req.params;
let found = false;
database.users.forEach((user) => {
if (user.id === id) {
found = true;
return res.json(user);
}
if (!found) {
res.json("User not found");
}
});
});
From the MDN Web Docs:
There is no way to stop or break a forEach() loop other than by throwing an exception. If you need such behavior, the forEach() method is the wrong tool.
Early termination may be accomplished with:
A simple loop
A for...of
loop
[Array.prototype.every()][every]
[Array.prototype.some()][some]
[Array.prototype.find()][find]
[Array.prototype.findIndex()][findIndex]
This means that your loop will run through all elements and in fact call res.json multiple times resulting in the ERR_HTTP_HEADERS_SENT error . There are many ways to fix this, here's an one example:
app.get("/profile/:id", (req, res) => {
const {id} = req.params;
for (const user of database.users) {
if (user.id === id) {
return res.json(user);
}
}
res.json("User not found");
});

Can't acces specific values in my node.js mongoose Model (only the Object)

I have been working at this for the past 4 hours. I would therefore like some help. I want to access the specific values in my database, eg. as response.data.values.imglink although when adding imglink in console.log() I get undefined. I can get the general object but not the specifik values.
I have defined my Song Schema as:
const songSchema = new Schema({
values: [{
imglink: {
type: String
},
id: {
type: String
},
spotify: {
type: String,
},
soundCloud: {
type: String,
},
youtube: {
type: String,
},
appleMusic: {
type: String,
}}
],
}, {
timestamps: true,
})
As you can see values is an array of objects. People with a similiar problem on here hadn't included the correct values in their Schema, so maybe that's my problem? Although to me it looks correct. I then GET the values in my database. The JSON object usually looks something like this:
[
{
"_id": "5ffbba4dc47e847a79c9c68f",
"values": [
{
"_id": "5ffbba4dc47e847a79c9c690",
"imglink": "imagelink",
"id": "id",
"soundCloud": "soundcloudvalue",
"youtube": "youtubevalue",
"appleMusic": "applemusicvalue",
"spotify": "spotifyvalue"
}
]
}
]
I call it by this function, which is supposed to print out the individual values:
const getAllSongs = () => {
axios.get('http://localhost:5000/songs/'+id)
.then(function (response) {
console.log(response); // returns an object
console.log(response.data.values.imglink); // returns an object
})
.catch(function (error) {
// handle error
console.log(error);
})
}
I have an Express route object that allows me to access a song by it's id as GET http://localhost:5000/songs/id in the VS-code HTTP client (similiar to postman):
router.get(`/:id`, function(req, res) {
return Song.find(
{"values.id": req.params.id}
).then(function(song) {
// return orders when resolved
res.send(song);
console.log(id);
res.json('works yesss');
})
.catch(function (err) {
// handle error
res.status(400).json('Error: '+err)
})
});
Here are some popular solutions I have tried:
Wrapping response in JSON.stringify() doesn't work.
toObject() and toJSON() don't work either as they aren't defined when I use them.
the _doc hack doesn't work either.
I have tried looking at the Schema which is where I think the problem is. The POST-request adds the right data, the GET-request goes through I just can't acces the specific values.
I hope you have the time to help, thanks. I will be extremely grateful. And of course let me know if you have any questions.
the result of find() is a Array so to access the desired key, if length of result Array is one, to access the desired key is response.data[0].values[0].imglink.
note: the values key is a array of obejct
If the array size is more than one, you want to see the result, you can use map()
if it's not worked, using lean() like this
router.get(`/:id`, function(req, res) {
return Song.find(
{"values.id": req.params.id}
).lean().then(function(song) {
// return orders when resolved
res.send(song);
console.log(song[0].values[0].imglink); // type of song is array of object [] and values is array
res.json('works yesss');
})
.catch(function (err) {
// handle error
res.status(400).json('Error: '+err)
})
});

Posting multiple documents using postman not working

I'm trying to post data using postman, but when I tried to use multiple documents, it shows blank in my mongodb. But when I try to insert a single document, it saves the data. Please correct me, I'm new to this
server.js
app.post('/bloodinventory', function(req, res) {
var bloodinventory= new Bloodinventories();
bloodinventory.blood_group = req.body.blood_group;
bloodinventory.blood_category = req.body.blood_category;
bloodinventory.num_stock = req.body.num_stock;
bloodinventory.save(function(err) {
if (err) {
res.json({ success: false, message: 'Blood Donation already exists!' });
} else {
res.json({ success: true, message: 'Blood Donation Created!' });
}
});
});
Then in my postman, I tried to insert this data:
{
"bloodinventories":[
{
"blood_group":"A_positive",
"blood_category":"whole blood",
"num_stock":11
},
{
"blood_group":"A_negative",
"blood_category":"platelet",
"num_stock":9
}
]
}
Then nothing shows in my mongodb, result:
_id:5c45c6a495788ec2c47f8c8b
__v:0
When you provide single document in your POST request
Example:-
{
"blood_group":"A_positive",
"blood_category":"whole blood",
"num_stock":11
}
it easly get request.body.blood_group, request.body.blood_category and show on
But when you pass Mutliple document in POST request in array form
{
"bloodinventories":[
{
"blood_group":"A_positive",
"blood_category":"whole blood",
"num_stock":11
},
{
"blood_group":"A_negative",
"blood_category":"platelet",
"num_stock":9
}
]
}
Now your request is getting a array so your request body contain bloodinventories. And you can access it as request.body.bloodinventories
Take this const and apply loop on it and insert all document.
Or Simply make API like this and always send array in every request of insert.
Bloodinventories.insertMany(request.body.bloodinventories).then((result) => {
//Success Message
}).catch(err => {
// Error Message
});
It May Help For You...

What is the perfect replace of toInclude() assertion in expect new version?

Stuck with this.I am trying to test my login API using expect and new version of expect throwing me some error.
That's my testing code.
it('should login user and return auth token', (done) => {
request(app)
.post('/users/login')
.send({
email : users[1].email,
password : users[1].password
})
.expect((res) => {
expect(res.headers['x-auth']).toBeTruthy();
})
.end((error,res) => {
if(error)
{
return done(error);
}
User.findById(users[1]._id).then((user) => {
expect(user.tokens[0]).toMatchObject({
access : 'auth',
token : res.headers['x-auth']
});
done();
}).catch((error) => done(error));
});
});
And error is
1) POST /users/login
should login user and return auth token:
Error: expect(received).toMatchObject(expected)
Expected value to match object:
{"access": "auth", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1OWYwMzM0ZGExMzRmYjFmNzg4NTkzOTciLCJhY2Nlc3MiOiJhdX
RoIiwiaWF0IjoxNTA4OTE0MDEzfQ.S0KCmLADcCLPWTK1khxNPO03tVMTW0HU117xapm56MM"}
Received:
{"_id": "59f0335da134fb1f788593b3", "access": "auth", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1OWYwMzM0ZGExMzR
mYjFmNzg4NTkzOTciLCJhY2Nlc3MiOiJhdXRoIiwiaWF0IjoxNTA4OTE0MDEzfQ.S0KCmLADcCLPWTK1khxNPO03tVMTW0HU117xapm56MM"}
Difference:
- Expected
+ Received
Object {
+ "_id": "59f0335da134fb1f788593b3",
"access": "auth",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1OWYwMzM0ZGExMzRmYjFmNzg4NTkzOTciLCJhY2Nlc3MiOiJhdXRoIiwiaWF0IjoxNTA
4OTE0MDEzfQ.S0KCmLADcCLPWTK1khxNPO03tVMTW0HU117xapm56MM",
}
I am testing two things but the code itself including _id and showing me that error. In previous version of expect (when Jest was not introduced) it was simple using toInclude() assertion,but now both toContain() and toMatchObject() showing same error.
That's my seed file
const{ObjectID} = require('mongodb');
const jwt = require('jsonwebtoken');
const {Todo} = require('./../../models/todo');
const {User} = require('./../../models/user');
const userOneId = new ObjectID();
const userTwoId = new ObjectID();
const users = [{
_id: userOneId,
email: 'adil.aj95#gmail.com',
password : 'userOnePass',
tokens: [{
access : 'auth',
token : jwt.sign({_id : userOneId,access : 'auth'}, 'abc123').toString()
}]
},
{
_id: userTwoId,
email: 'adil2.aj95#gmail.com',
password : 'userTwoPass',
// tokens: [{
// access : 'auth',
// token : jwt.sign({_id : userTwoId,access : 'auth'}, 'abc123').toString()
// }]
}];
You need just a slight change. Instead of using
expect(user.tokens[0]).toMatchObject({
access : 'auth',
token : res.headers['x-auth']
});
include .toObject() after user like this
expect(user.toObject().tokens[0]).toMatchObject({
access : 'auth',
token : res.headers['x-auth']
});
Why? Your user is a mongoose object that has more info than you would expect. You can see that there is an extra _id property in the token (the error that is thrown shows that). What toObject() does is it returns just the object as you would expect it, without all the mongoose-specific properties (stuff like _id, __v etc).
You can use .toHaveProperty(keyPath, value) for the new expect version by jest.
So the code becomes like this:
expect(user.tokens[0]).toHaveProperty('access', 'auth');
expect(user.tokens[0]).toHaveProperty('token', user.tokens[0].token);

Resources