I am using NestJS and wondering how would you add a status to the response object. Say I have this controller method:
#Get()
ping(): string {
return this.appService.ping();
}
That return a string like '24 March 2020 16:56:07'. What I want is to add the status code to the response so my response and error message so the response would looks looks like this:
{
result: "24 March 2020 16:56:07"
status: "OK"
errorMessage: ""
}
Is there anyway to achieve that using some nestjs built in features?
UPDATE:
The solution proposed by #Hitech-Hitesh it is not something I am looking for, I want to buildup the response object automatically so I do just return result from the controller method return this.appService.ping(); and then something else taking place and builds up the response object.
You can do in your service file like this >
getData(): Message {
// return { message: 'Welcome to api!' };
return { message: '' };
}
ping() {
if (this.getData().message !== '') {
return { status: 'OK', errorMessage: '', result: this.getData().message };
}
else {
return { status: 'FAIL', errorMessage: 'Not able to fetch the result. Please try again later', result: '' };
}
}
when the ping file is called from the controller it will directly give the result
#Get()
ping(): any {
return this.appService.ping();
}
You can do this directly in your controller also but checking the service response.
#Get()
ping(): any {
const pingServiceResponse = this.appService.ping();
if (pingServiceResponse !== '')
return { status: 'OK', errorMessage: '', result: pingServiceResponse };
else
return { status: 'FAIL', errorMessage: 'Not able to fetch the result. Please try again later', result: pingServiceResponse };
// return this.appService.ping();
}
Related
I am making a code snippet web app. Basically you can upload snippets and organize them, etc. I am having trouble deciding how to store the code.
Currently, I am using express to create an API to connect to the frontend. I am inserting whatever code was inputted in the textarea, and saving it in plaintext to mongodb.
let snippet = new Snippet({
title: req.body.title,
code: req.body.code,
creator: req.body.creator,
createdDate: date,
updatedDate: date,
collections: req.body.collections,
});
await snippet.save((error, Snippet) => {
if (error) {
console.log(
"postSnippet(): Failed to save snippet to database. Error: " +
error
);
return res
.status(500)
.json({ message: "Failed to save snippet to database" });
} else {
console.log("postSnippet(): Snippet created.");
return res
.status(201)
.json({ message: "Snippet created", snippet });
}
});
When I paste the code on the UI frontend, it displays just fine. But for some reason, when I try to get the raw code in a seperate file, all the line breaks dont work.
export const fetchRawSnippet = async (req, res) => {
let snippetUrl = req.params.slug;
if (snippetUrl) {
try {
const fetchSnippets = await Snippet.findOne({ slug: snippetUrl });
if (fetchSnippets) {
res.send(fetchSnippets.code);
return res.status(200).json(fetchSnippets.code);
} else {
return res
.status(404)
.json({ message: "Could not find snippet" });
}
} catch (e) {}
} else {
return res.status(404).json({ message: "slug not provided" });
}
};
I am wondering if its a better idea to use GitHub Gists API to host the snippets...
Im not sure. Can someone just guide me in the right direction about the best way to go about code storage.
I am new to loopback I want to change every response from my loopback remote method API to a particular format
eg: if success
{
status:1,
data:{},
message:"Success"
}
If error
{
status:0,
data:{},
message:"Something went wrong"
}
You should create a boot script to change all remote method responses :
Create hook.js or any other name in /server/boot/
module.exports = function (app) {
var remotes = app.remotes();
// modify all returned values
remotes.after('**', function (ctx, next) {
if (ctx) {
ctx.result = {
status: 1,
data: ctx.result,
message: "Success"
};
} else {
var err = new Error();
next({
status: 0,
data: err,
message: "Something went wrong"
});
}
next();
});
};
Check these links for more information :
Formatting remote method responses (Last Section)
https://loopback.io/doc/en/lb3/Remote-methods.html
Hooks
https://loopback.io/doc/en/lb3/Strong-Remoting.html
I got this error: Falsy value for recipient key 'registrationTokens' while working with gcm push notifications.
Below you can find my code:
Device.find({ user: { $in: users }}, function (err, devices) {
if (err) {
logger.error('500 ' + err)
return res.status(500).json({
code: config.errorCode.status500.code,
message: config.errorCode.status500.message
})
}
var androidRegTokens = []
var iOSReqTokens = []
for (var i = 0; i < devices.length; i++) {
if (devices[i].platform == 'Android') {
androidRegTokens.push(devices[i].deviceToken)
} else {
iOSReqTokens.push(devices[i].deviceToken)
}
}
if (androidRegTokens.length > 0) {
gcmPush('Notification is sent.', androidRegTokens)
}
if (iOSReqTokens.length > 0) {
apnsPush('Notification is sent.', iOSReqTokens)
}
return res.json({ msg: 'Operation succeed.'})
})
Body of the function gcmPush('Notification is sent.', androidRegTokens) is:
this.sender.send(message, { registrationTokens: deviceTokens }, function (err, response) {
if (err) {
console.error(err)
}else {
console.log(response)
}
})
Does anyone know what wrong is with my code? At first push notifications worked perfect, than this error occured each time I call the service.
EDIT:
I have solved this thanx to Luiz Fernando. The problem is the function:
gcmPush('Notification is sent.', androidRegTokens)
I have forgot to add title which is part of the constructor:
function GcmPush (title, message, deviceTokens) {
this.sender = new gcm.Sender(config.gcmSender)
this.sendPushNotification(title, message, deviceTokens)
}
The deviceTokens object is a falsy value, it can be: null, undefined, 0, '', NaN,false.
Maybe it happend because you are filling iOSReqTokens and androidRegTokens nested in an asynchronous operation (it seems Device.find is async). So, the callback of Device.find and the for-loop happens in different times. Probably, the for-loop is happening AFTER the response, so this response will be undefined (and really is).
So, you need to use some async control flow library, such Promise or Async and ensure the correct order of operations.
Also, where you use the pushed registrations?
I'm trying to do something like this:
var countElemnts = function() {
superagent
.get('/someOtherUrl')
.query({
type: value.type
})
.end(function(err, res) {
console.log(JSON.stringify(res.body));
if (res.ok) {
reply(JSON.stringify(res.body));
} else {
console.log(err);
}
})
};
superagent
.post('/someUrl')
.type('json')
.send({
name: 'value.update',
data: {
id: request.params.id,
type: value.type,
count: countElemnts()
}
})
.end(function() {
reply({
message: 'ok'
});
});
In data option of the send function I'm trying to call a function to obtain some value.
What I want is to get the value that comes in the body of a reply, ie the res.body. Upon console.log get this [{ "count ": 3 } ], but if I do a console.log of res.body.count tells me undefined, what could I do to get the value 3.
Thanks.
Since the return doesn't have the extra space in "count " (as mentioned in the comments) the problem was that you were trying to access the count attribute of the array and not the object (first element of the array), so to access it you should do it like:
res.body[0].count
As for the problem of not being able to get the count in your POST, the problem is that countElemnts uses an asynchronous function. The end method of superagent takes a function as parameter and it is only called when it receives a response. By that time, your function had already returned (with undefined, since you didn't return anything).
You should first make the GET call and then send it to a function that will handle the POST. For example:
superagent
.get('/someOtherUrl')
.query({
type: value.type
})
.end(function(err, res) {
if (err) {
console.log(err);
} else {
console.log(JSON.stringify(res.body));
sendCount(res.body[0].count)
}
});
function sendCount(count) {
superagent
.post('/someUrl')
.type('json')
.send({
name: 'value.update',
data: {
//id: request.params.id, // not sure where you are getting these values from,
//type: value.type, // but you should adapt it to your code
count: count
}
})
.end(function() {
reply({
message: 'ok'
});
});
}
Here is my code :
server.get(url_prefix + '/user/:user_id/photos', function(req, res, next) {
if (!req.headers['x-session-id']) {
res.send({
status: {
error: 1,
message: "Session ID not present in request header"
}
})
} else {
User.findOne({
session_id: req.headers['x-session-id']
}, function(err, user) {
if (user) {
var user_id = req.params.user_id
Album.find({userId : user_id})
.populate('images')
.exec(function (err, albums) {
if (albums) {
albums.forEach(function(album, j) {
var album_images = album.images
album_images.forEach(function(image, i) {
Like.findOne({imageID : image._id, userIDs:user._id}, function(err,like){
if(like){
albums[j].images[i].userLike = true;
}
})
})
})
return res.send({
status: {
error: 0,
message: "Successful"
},
data: {
albums: albums
}
})
} else
return notify_error(res, "No Results", 1, 404)
})
}
else {
res.send({
status: {
error: 1,
message: "Invalid Session ID"
}
})
}
})
}
})
I am trying to add a extra value (albums[j].images[i].userLike = true;) to my images array, which is inside album array.
The problem is return res.send({ send the data before we get response from the foreach
How can I make it work, so that return should happen only after foreach has completed all the iteration
You will have to wait with invoking res.send until you fetched all the likes for all the images in each of the albums. E.g.
var pendingImageLikes = album_images.length;
album_images.forEach(function(image, i) {
Like.findOne({imageID : image._id, userIDs:user._id}, function(err,like){
if (like) {
albums[j].images[i].userLike = true;
}
if (!--pendingImageLikes) {
// we fetched all likes
res.send(
// ...
);
}
});
You might need to special case for album_images.length === 0.
Also, this does not take into account that you have multiple albums with multiple images each. You would have to delay res.send there in a very similar way to make this actually work. You might want to consider using a flow control library like first (or any other of your preference, just search for "flow control library") to make this a bit easier.
Also, you might want to consider not relying on semicolon insertion and manually type your semicolons. It prevents ambiguous expressions and makes the code easier to read.
Since you need your code to wait until all of the find operations have completed, I'd suggest you consider using the async package, and specifically something like each (reference). It makes using async loops cleaner, especially when dealing with MongoDB documents and queries. There are lots of nice features, including the ability to sequentially perform a series of functions or waterfall (when you want to perform a series, but pass the results from step to step).
> npm install async
Add to your module:
var async = require("async");
Your code would look something like this:
albums.forEach(function(album, j) {
async.each(album.images, function(album, done) {
Like.findOne({imageID: image._id, userIDs:user._id}, function(err, like){
if(!err && like){
albums[j].images[i].userLike = true;
}
done(err); // callback that this one has finished
})
})
}, function (err) { // called when all iterations have called done()
if (!err) {
return res.send({
status: {
error: 0,
message: "Successful"
},
data: {
albums: albums
}
});
}
return notify_error(res, "No Results", 1, 404);
});
});