I've set up a node.js server-app that I want to do some parse.com requests.
I basically want it to return the parse-object JSON-representation.
My route:
var blog = require('./models/model');
app.get('/api/article/:permalink', function(req, res) {
res.json(blog.getArticle(req.params.permalink));
});
And my model:
var Parse = require('parse/node').Parse, // load the parse for node package
keys = require('../../config/keys'); // keys config-file for hosted services
Parse.initialize(keys.app, keys.js);
module.exports = {
getArticle: function(permalink) {
"use strict";
var Article = Parse.Object.extend('Article');
var query = new Parse.Query(Article);
query.include('category');
query.include('profile');
query.equalTo('permalink', permalink);
query.find().then(function(results) {
return results;
}, function(error) {
return error;
});
}
};
The thing is, this returns nothing when I call an article with a permalink that I know to exist (example: http://localhost/api/article/testFoo). I don't get any errors either.
My browser console flashes a message for a split second that reads:
Resource interpreted as Document but transferred with MIME type application/json: "http://localhost/api/article/testFoo"
Any suggestions to what I am doing wrong?
You are trying to use the return value of an async function. This can't work, you need to pass a callback (or the res object) to your getArticle function, which will then use it to send the data back.
With a callback:
app.get('/api/article/:permalink', function(req, res) {
blog.getArticle(req.params.permalink, function(data) {res.json(data)});
});
...
getArticle: function(permalink,callback) {
...
query.find().then(function(results) {
callback(results);
}, function(error) {
callback({error: error});
});
Related
I want to select data after inserting, so what i want is to check it every second if there is a new data. I create a select query then try to display it using console log. Please help me, I'm a newbie. Here is my code
Controller
var connection = require('../../config/db');
function myQuery(callback) {
this.pushActivity = function(req, res, next) {
var salesman_id = req.query.salesman_id
connection.acquire(function(err, con) {
con.query('SELECT * FROM `activities` where salesman_id="'+salesman_id+'" and kunci="0" and created=NOW()', function(err, data) {
con.release();
if (err) {
return res.json({ status: 400, message: 'Failed', result: [] });
} else {
console.log(data)
// return res.json(data);
}
});
});
};
callback();
}
function wait10sec(){
setTimeout(function(){
myQuery(wait10sec);
}, 10000);
}
myQuery(wait10sec);
module.exports = new myQuery();
Router
var ad =
require('./../../controllers/mobile/activity_after_deal');
module.exports = {
configure: function(app) {
app.route('/api_ad_push_notif').get(ad.pushActivity);
}
};
This is not a good and efficient approach .Instead of using this ,try to use listener on put request which changes the data and after change event,execute the Get query and output the changed data.Use Socket.io Library for such purposes.
you can use socket.io .
by this module you can send live event to server and get response.
for example when send new data, you can select query or send emit to user or show it on console log
You can create worker by adding
setInterval(function(){
//run query and console
}, 1000) and you can set time
I am releasing access to pages using connect-roles and loopback but I have a pertinent question about how I can collect the customer's role and through the connect-roles to read the session and respond to a route.
Example, when the client logs in I load a string containing the client's role and access it in a function that controls access to pages.
I have this doubt because I'm finalizing a large scale service that usually there are multiple client sessions that are accessed instantly using a same storage and check function.
It would be efficient to store the customer's role using app.set() and app.get()?
app.get('/session-details', function (req, res) {
var AccessToken = app.models.AccessToken;
AccessToken.findForRequest(req, {}, function (aux, accesstoken) {
// console.log(aux, accesstoken);
if (accesstoken == undefined) {
res.status(401);
res.send({
'Error': 'Unauthorized',
'Message': 'You need to be authenticated to access this endpoint'
});
} else {
var UserModel = app.models.user;
UserModel.findById(accesstoken.userId, function (err, user) {
// console.log(user);
res.status(200);
res.json(user);
// storage employee role
app.set('employeeRole', user.accessLevel);
});
}
});
});
Until that moment everything happens as desired I collect the string loaded with the role of the client and soon after I create a connect-roles function to validate all this.
var dsConfig = require('../datasources.json');
var path = require('path');
module.exports = function (app) {
var User = app.models.user;
var ConnectRoles = require('connect-roles');
const employeeFunction = 'Developer';
var user = new ConnectRoles({
failureHandler: function (req, res, action) {
// optional function to customise code that runs when
// user fails authorisation
var accept = req.headers.accept || '';
res.status(403);
if (~accept.indexOf('ejs')) {
res.send('Access Denied - You don\'t have permission to: ' + action);
} else {
res.render('access-denied', {action: action});
// here
console.log(app.get('employeeRole'));
}
}
});
user.use('authorize access private page', function (req) {
if (employeeFunction === 'Manager') {
return true;
}
});
app.get('/private/page', user.can('authorize access private page'), function (req, res) {
res.render('channel-new');
});
app.use(user.middleware());
};
Look especially at this moment, when I use the
console.log(app.get('employeeRole')); will not I have problems with simultaneous connections?
app.get('/private/page', user.can('authorize access private page'), function (req, res) {
res.render('channel-new');
});
Example client x and y connect at the same time and use the same function to store data about your session?
Being more specific when I print the string in the console.log(app.get('employeeRole')); if correct my doubt, that I have no problem with simultaneous connections I will load a new variable var employeeFunction = app.get('employeeRole'); so yes my function can use the object containing the role of my client in if (employeeFunction === 'Any Role') if the role that is loaded in the string contain the required role the route it frees the page otherwise it uses the callback of failureHandler.
My test environment is limited to this type of test so I hope you help me on this xD
Instead of using app.set you can create a session map(like hashmaps). I have integrated the same in one of my projects and it is working flawlessly. Below is the code for it and how you can access it:
hashmap.js
var hashmapSession = {};
exports.auth = auth = {
set : function(key, value){
hashmapSession[key] = value;
},
get : function(key){
return hashmapSession[key];
},
delete : function(key){
delete hashmapSession[key];
},
all : function(){
return hashmapSession;
}
};
app.js
var hashmap = require('./hashmap');
var testObj = { id : 1, name : "john doe" };
hashmap.auth.set('employeeRole', testObj);
hashmap.auth.get('employeeRole');
hashmap.auth.all();
hashmap.auth.delete('employeeRole');
I'm using Express, Node.js and a Mongo DB. I've simplified this code somewhat from my actual code to try to cut out the noise, I hope it makes sense.
My basic problem is that I'm modifying an object and I am expecting the data change to persist across client-server calls, but it isn't. The comments explain more.
// server side routes.js
var LM = require('./modules/login-manager'); // database accessing functions
var DM = require('./modules/data-manager'); // database accessing functions
module.exports = function (app) {
app.post('/', function (req, res) {
// LM.manualLogin does a MongoDB call that looks fine, returns the expected data
LM.manualLogin(req.body['user'], req.body['pass'], function (e, o) {
if (!o) {
res.status(400).send(e);
} else {
req.session.user = o;
// calculateRank adds arbitrary fields to the user object
// this change persists to POST /dashboard
calculateRank(req.session.user);
// DM.getListOfData() does a Mongo DB call that looks fine
// and returns the expected data in o
DM.getListOfData(function (e, o) {
if (!o) {
res.status(400).send(e);
} else {
// availableData doesn't already exist. This assignment
// operation looks good
// in the debugger, but "availableData" is NOT in the
// req.session when we get to POST /dashboard
req.session.availableData = o;
}
});
res.status(200).send(o);
}
});
});
app.get('/dashboard', function (req, res) {
if (req.session.user == null) {
res.redirect('/');
}
else {
// "availableData" is not there!
// but changes to req.session.user are
res.render('dashboard', {
user: req.session.user,
data: req.session.availableData
});
}
});
}
// client side
$('#login').ajaxForm({
beforeSubmit: function (formData, jqForm, options) {
formData.push({
name: 'remember-me',
value: $('.button-rememember-me-glyph').hasClass('glyphicon-ok')
});
return true;
},
success: function (responseText, status, xhr, $form) {
if (status == 'success') window.location.href = '/dashboard';
},
error: function (e) {
// login error
}
});
So I click my login button that drives the client-side ajax function. Server side, I get the POST / and when that returns, client side redirects to /dashboard. The problem is that server side, in POST /dashboard some of my data is missing. The thing I really don't understand is that the data set by "req.session.user = o;" and "calculateRank(req.session.user)" persists. The data set by "req.session.availableData = o;" doesn't, in POST /dashboard it is as if the operation never happened (but the other two did). When I debug that assignment operation it looks fine and I can see the data in the req object.
Can anyone help explain this to me please? Thanks!
You're sending the response, res.status(200).send(o);, before req.session.availableData = o; has had time to run, since it's an async operation.
Sending the response inside the getListOfData callback would fix your problem.
I am new to NodeJS. I am using NodeJS on server side. I am trying to make a simple REST based GET request which takes search parameter searchvar from user and returns the matching records found in a JSON array. My server code is as follows:
var express = require('express');
var app = express();
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var ObjectId = require('mongodb').ObjectID;
var url = 'mongodb://localhost:27017/mydb';
app.get('/search', function(req, res) {
res.set({ 'content-type': 'application/json; charset=utf-8' });
res.header("Content-Type", "application/json; charset=utf-8");
res.charset = 'utf-8';
var searchvar = req.query.searchvar;
if(searchvar != null) {
var recordsArray = new Array();
console.log("searchvar :: " + searchvar );
MongoClient.connect(url, function(err, db) {
var cursor = db.collection('myCollections').find({"name": new RegExp(searchvar)});
cursor.each(function(err, doc) {
//assert.equal(err, null);
if (doc != null) {
var tempObject = {"name": doc.name, "cat": doc.cat};
recordsArray.push(tempObject);
console.dir(doc);
} else {
db.close();
}
});
if(recordsArray.length > 0) {
console.log("if........");
res.json({"status": "SUCCESS", "message": "The request processed successfully.", "records":recordsArray});
} else {
console.log("else........");
res.json({"status": "FAILURE", "message": "No records found corresponding to given search query."});
}
});
} else {
res.json({"status": "FAILURE", "message": "The searchvar is missing."});
}
//res.send('id: ' + req.query.id);
});
app.listen(3000);
When I call it with RESTClient in a browser with following URL:
http://localhost:3000/search?searchvar=aa
I get following response:
{"status": "FAILURE", "message": "No records found corresponding to given search query."}
It is an async call. I want to know the process in server using which i can return the response when the processing is done and handle this async response on client side.
Thanks in advance.
The response occurs because the if check:
if(recordsArray.length > 0) {
console.log("if........");
is executed before the callback passed to the cursor.each method has completed its processing. As a result, the array is empty.
Proposed solution
The cursor.forEach method takes a callback function that is executed asynchronously. This means you can access the results of the callback's execution only within the callback itself (except you return a Promise object). A fix would be:
cursor.forEach(function(doc) {
if (doc != null) {
var tempObject = {"name": doc.name, "cat": doc.cat};
recordsArray.push(tempObject);
console.dir(doc);
}
}, function(err) {
if(recordsArray.length > 0) {
console.log("if........");
res.json({"status": "SUCCESS", "message": "The request processed successfully.", "records":recordsArray});
} else {
console.log("else........");
res.json({"status": "FAILURE", "message": "No records found corresponding to given search query."});
}
db.close();
});
I think you're missing the callback parameter to the MongoClient Collection find() method. You should move your handling logic into the callback.
See these examples in the MongoDB documentation.
Your code would look something like this:
db.collection('myCollections').find({"name": new RegExp(searchvar)}).toArray(function(err, docs) {
// iterate through docs; perform your logic
db.close();
res.json({...});
});
I think your best bet is to go through a Nodejs/MongoDB tutorial to understand how everything works. From a quick look at your code your response is not asynchronous. Any time the server responds right aways it's not async. Async is achieved on the server side when you implement something like Websockets or HTTP Callbacks.
I agree with Jim that the problem is probably in your client (please post the code if you still have questions). Generally a JS client achieves async by using callbacks or promises, but an async client does not require an async server. The reason it is common to make async client calls is so you don't lock up your GUI while waiting for a response from the server.
I am facing an issue in parse cloud code. The following is updating score and change date in my gamescore table. But it is not working. while I am doing same in my web code and it is working fine. Am I doing anything wrong here ?
'use strict';
var GameScore = Parse.Object.extend('GameScore');
Parse.Cloud.define('editScore', function(req, res) {
var query = new Parse.Query(GameScore);
query.get(req.params.objectId, {
success: function(gameScore) {
gameScore.set('score', req.params.score);
gameScore.set('date', req.params.date);
gameScore.save(null);
gameScore.fetch(myCallback);
},
error: function(err) {
return res.error(err);
}
});
});
If so then please help me so that I can make it working.
Try adding Parse.Cloud.useMasterKey(); inside the function to bypass any ACL restrictions that could be causing an issue. Example:
var GameScore = Parse.Object.extend('GameScore');
Parse.Cloud.define('editScore', function(req, res) {
// use Master Key to bypass ACL
Parse.Cloud.useMasterKey();
var query = new Parse.Query(GameScore);
query.get(req.params.objectId, {
success: function(gameScore) {
gameScore.set('score', req.params.score);
gameScore.set('date', req.params.date);
gameScore.save(null);
gameScore.fetch(myCallback);
},
error: function(err) {
return res.error(err);
}
});
});
You have 3 issues:
you're not waiting for the save to finish
you're not calling res.success()
you're referencing myCallback which from what you've shown us isn't defined
Simple solution is to replace this line:
gameScore.save(null);
With this code:
gameScore.save().then(function () {
res.success();
});
If you really do need that fetch call you would chain that in:
gameScore.save().then(function () {
return gameScore.fetch(myCallback);
}).then(function () {
res.success();
});
var GameScore = Parse.Object.extend('GameScore');
Parse.Cloud.define('editScore', function(req, res) {
Parse.Cloud.useMasterKey();
var query = new Parse.Query(GameScore);
query.get(req.params.objectId, {
success: function(gameScore) {
gameScore.set('score', req.params.score);
gameScore.set('date', req.params.date);
gameScore.save().then(function() {
gameScore.fetch(callback);
});
},
error: function(err) {
return res.error(err);
}
});
});
using master key we are overriding acl. using then promise method we are calling callback functions after otherwise there is a possibility to get the old data.