Unable to access get method from request package in the function node - node.js

I have added request module and made changes in main settings.js as per the documentation :
// Anything in this hash is globally available to all functions.
// It is accessed as context.global.
// eg:
// functionGlobalContext: { os:require('os') }
// can be accessed in a function block as:
// context.global.os
functionGlobalContext: {
requestModule:require('request').defaults({jar: true})
// os:require('os'),
// octalbonescript:require('octalbonescript'),
// jfive:require("johnny-five"),
// j5board:require("johnny-five").Board({repl:false})
},
This is the code in one of my function nodes :
var request = context.global.requestModule;
request.get('http://192.168.0.44:3000' + '/api/stats',
function (err, data) {
if (err) {
console.log("could not process data");
}
else {
var body = JSON.parse(data.body);
msg.payload = body.deviceCount;
}
});
return msg;
My node red version is (0.16.2)

That won't work because you return msg before the async call back in the request object is called. The following should work:
var request = context.global.requestModule;
request.get('http://192.168.0.44:3000' + '/api/stats',
function (err, data) {
if (err) {
console.log("could not process data");
}
else {
var body = JSON.parse(data.body);
msg.payload = body.deviceCount;
node.send(msg)
}
});

Related

Http requests inside a for loop from angular to node.js API returns 404

I try to send several HTTP requests continuously inside a for loop to node.js rest API.
Below is how I try to send HTTP requests from my Angular Front-end.
getOthersCompletionsByTaskID is the function that send a HTTP request.
this.tasksService.getTasks().then(res=>{
let i=0;
for(i;i< this.tasksService.tasks.length; i++){
this.completionService.getOthersCompletionsByTaskID(this.tasksService.tasks[i].TaskId).then(res =>{
let cArray: any = res;
console.log("cArray ", cArray)
})
}
this.dtTrigger.next();
this.rendMyTasksTable();
})
Below is my query execution function in node API.
function queryGetExecute(qry, params, isMultiSet, callback) {
var data = [];
var dataset = [];
var resultset = 0;
request = new Request(qry, async function (err, rowCount) {
utility.sendDbResponse(err, rowCount, dataset, callback);
});
params.forEach( param => {
request.addParameter(param.name, param.type, param.val);
});
request.on('row', async function (columns) {
utility.buildRow(columns, data);
});
request.on('doneInProc', async function (rowCount, more, rows) {
if (isMultiSet == false) {
dataset = data;
} else {
dataset.push(data);
data = [];
}
});connection.execSql(request)}
Below is the function in the repository that calls the above function.
function getCompletionsByFirebaseId(req, res){
if (req.params.firebaseId && req.params.taskId) {
var parameters = [];
parameters.push({ name: 'firebaseId', type: TYPES.NVarChar, val: req.params.firebaseId});
parameters.push({ name: 'taskId', type: TYPES.NVarChar, val: req.params.taskId});
var query = "select users.[name], completedById, [status], completionImage,completionId,exchangeTaskId from Tasks join completions on Tasks.TaskId=completions.taskId join users on users.firebaseId = completions.completedById where taskownerId=#firebaseId and Tasks.TaskId = #taskId"
dbContext.getQuery(query, parameters, false, function (error, data) {
if (data) {
req.data = data[0];
let finaldata = res.json(response(data, error));
return finaldata
}else{
return res.sendStatus(404);
}
});
}else
{
return res.sendStatus(404)
}
}
When I do requests like this, API returns 404. but the first request is becoming successful. rest requests returning 404. What am I doing wrong here?

before fetching data in db response is sent by node js

this is my set notification object
var sentNotificationObj = function (notification, eventid, addedorganizerpropic) {
this.notification = notification;
this.eventid = eventid;
this.addedorganizerpropic = addedorganizerpropic;
}
this is my array which is stored notification obect
var notificationSetArray2 = [];
this is my api of getnotification
router.post('/getnotification', function (req, res) {
console.log('in aside');
var id = req.body.userid;
console.log('pos id' + id);
User.findById({ _id: id }, function (err, result) {
if (err) {
console.log('err get notification');
res.statusCode = 500;
res.json({
success: false,
message: "severe error"
});
} else {
this is code fetchin data in data base
for (var i = 0; i < result.notification.length; i++) {
var addedevent = result.notification[i].addedevent;
var notification = result.notification[i].notification;
console.log('added event' + addedevent);
console.log('added noti' + notification);
User.findById({ _id: result.notification[i].addedorganizer }, function (err, addedorganizer) {
if (err) {
console.log('error get added user pofile pic');
} else {
convert image to base64
var base64str = base64_encode(addedorganizer.profileData.profileurl);
console.log(base64str);
console.log(notification);
console.log(addedevent);
var newsentNotificationObj = new sentNotificationObj(notification, addedevent, base64str);
notificationSetArray2.push(newsentNotificationObj);
console.log('succe get added user profile pic');
}
});
}
this is response
res.statusCode = 200;
res.json({
success: true,
notificationArray: notificationSetArray2
})
console.log(notificationSetArray2);
notificationSetArray2.length = 0;
}
});
});
The most simple solution in here to use async library here.
Node runs code in asynchronous way. So it is natural to send response before fetching any data from your database.
By using async you can execute this in a sequence. So it will be solved.
Use async.series method for solve this. For example
async.series(
[
function(callback){
// fetch your data here using mongo with your loop
//
//
callback(); // this will trigger next step (call this after you finished iterating array)
},
function(callback){
// after above code has been executed
// send response here
callback() // call this to proceed
}
],
function(err){
// handle any error in here
}
)
A good example of how to use asyncjs in node

How to make a webservice call synchronous in meteor

I am trying to call a simple weather service synchronously in meteor. I am not even able to make the client creating synchronous. In the code below I expect user.testData to contain "test data" but it contains nothing.
if (Meteor.isClient) {
Template.confirmWeather.onRendered(function(){
var validator = $('.confirmWeatherAndGoToMessage').validate({
submitHandler: function(event){
Meteor.bindEnvironment(Meteor.call('testWeather',Meteor.bindEnvironment(function(error,result)
{
if (error)
{
console.log(error.message)
}
else
{
var userId = Meteor.userId();
var user = Meteor.users.findOne({_id: userId});
if (user.testData)
{
console.log(user.testData);
}
}
})));
}
});
});
}
if (Meteor.isServer) {
Meteor.methods({
testWeather: function () {
var soap = Npm.require('soap');
var options = {
ignoredNamespaces: {
namespaces: [],
override: true
}
}
var url = 'http://www.webservicex.com/globalweather.asmx?WSDL';
Meteor.wrapAsync(soap.createClient(url, options,Meteor.bindEnvironment(function(err, client) {
if (err)
{
console.log("CREATE ERROR:");
console.log(err);
}
else
{
Meteor.wrapAsync(Meteor.call("insertIntoTestData","test data",function(err,res)
{
if (err)
{
throw new Meteor.Error("server-error",error.message);
}
else
{
console.log('DATA: ');
}
}));
}
})));
},
insertIntoTestData: function(data) {
var userId = Meteor.userId();
var user = Meteor.users.findOne({_id: userId});
if (user)
{
return resultId = Meteor.users.update({_id:userId},{$set:{testData:data}});
}
}
});
}
If you can't make that approach work maybe i can offer alternative. When i needed sync calls with request library i used different approach by using future library from fibers/future nodejs. After the request i just put "future.wait()" and inside async code callback "future.return(value)". Execution would then wait until request was finished and returned a value.
This link here nicely explains use of that approach also: https://themeteorchef.com/tutorials/synchronous-methods
Best regards,
Dino

unable to return in node.js from a function

I have three blocks of code where block one executes first and the result of first block is passed to bloack 2 and then the final result is then passed to the third block which has to send data to the route.
But at the end the return is undefined.
function getUserKey(userRole, callback) {
//keys value is stored and returned
var keys = base.menuModel.find({ 'name' : userRole }, function (err, result) {
if (!err) {
var menu = JSON.stringify(result);
menu = JSON.parse(menu);
var menuKeys = [];
for(i = 0;i < Object.keys(menu[0].permissions[0]).length;i++) {
menuKeys.push((Object.keys(menu[0].permissions[0])[i]));
}
callback(null,menuKeys);
//returns menukeys to be shown
}
else {
return err;
}
});
}
n is holding the menu keys
function userMenuData(n, callback) {
var filterResult = base.globalMenuModel.find({"title" : { $in : n}},function (err, result) {
if (!err) {
callback(null,result);
}
else {
return err;
}
});
}
var userMenu = function(userRole,callback) {
var userMenuTemp = async.compose(userMenuData, getUserKey);
var sendData = userRole is passed and the result is obtained
userMenuTemp(userRole,function(err,result) {
return result; // data success
});
console.log(sendData); //undefined
return sendData;
}
here i want to pass sendData to route in node.js
but at the console i am getting undefined.
Thanks for any help
It's the async nature of node that's getting you. The console.log is happening before any of those functions are returned. You want to check out a library that does promises like Q http://documentup.com/kriskowal/q/

node.js fall through data cache pattern

I am looking for a clean way to structure my node.js code for the following situation. I thought of using EventEmitters to create a "workflow" type of thing. Also I thought of using one of the async libraries out there, that has been less thought out though.
Problem:
Looking for a piece of data
check cache, if found return
check db, if found return (store in cache)
get live data and return, (store in db, cache)
I mocked something up quickly using event emitters below.
var util = require("util");
var events = require('events');
var CheckForData = function() {
events.EventEmitter.call(this);
this.checkForData = function(key) {
this.emit("checkForDataRequest", key);
}
var _checkCache = function(key) {
if (key === 'cache') {
this.emit("found", {data:'cached data'});
}
else {
console.log("not found in cache "+key);
this.emit("checkDatastore", key);
}
}
var _chechDatastore = function(key) {
if (key === 'db') {
this.emit("found", {data:'db data'});
this.emit("storeCache", key, {data:'db data'});
}
else {
console.log("not found in db "+key);
this.emit("getData", key);
}
}
var _getData = function(key) {
if (key === 'live') {
this.emit("found", {data:'live data'});
this.emit("storeData", key, {data:'live data'});
}
else {
console.log("not found in live "+key);
this.emit("notFound", key);
}
}
var _storeData = function(key, data) {
this.emit("storeDb", key, data);
this.emit("storeCache", key, data);
}
var _storeDb = function(key, data) {
console.log("storing data in db. for "+key);
console.log(data);
}
var _storeCache = function(key, data) {
console.log("storing data in cache. for "+key);
console.log(data);
}
var _found = function(data) {
return data;
}
var _notFound = function(key) {
return key;
}
this.on("checkForDataRequest", _checkCache);
this.on("checkDatastore", _chechDatastore);
this.on("getData", _getData);
this.on("found", _found);
this.on("notFound", _notFound);
this.on("storeData", _storeData);
this.on("storeDb", _storeDb);
this.on("storeCache", _storeCache);
};
util.inherits(CheckForData, events.EventEmitter);
module.exports = new CheckForData();
To test it...
var checkForData = require('./check-for-data');
checkForData.on("found", function(data) {
console.log("Found data ");
console.log(data);
});
checkForData.on("notFound", function(key) {
console.log("NOOO Found data for " + key);
});
console.log("-------");
checkForData.checkForData('cache');
console.log("-------");
checkForData.checkForData('db');
console.log("-------");
checkForData.checkForData('live');
console.log("-------");
checkForData.checkForData('other');
console.log("-------");
Then async.js, i made a quick checkSeries which is basically the async.detectSeries but instead of returning the item in the collection return the result. See below...
var async = require('async');
function check_cache(key) {
console.log('checking cache');
return null;
}
function check_datastore(key) {
console.log('checking datastore');
return null;//{data: "db data"};
}
function check_api(options) {
console.log('calling api');
return {data: "live data"};
}
function exists(item, callback) {
callback(item());
}
async.checkSeries([check_cache, check_datastore, check_api], exists, function(result) {
// result now equals the first function that return data
console.log(result);
});
Any suggestions, hints, tips, ...? Is there a pattern or library that i am missing? Do you think it be possible/easier to do in Step, flow, ...? Memoize?
That seems like a lot of work for the caller and a lot of extra code that doesn't seem to be adding much value. I have something that looks like this in my model.
Foo.get = function (id, cb) {
var self = this;
// check the cache first
cache.get('foo:' + id, function (err, cacheFoo) {
// if found, just return it
if (!err && cacheFoo) {
return cb(null, cacheFoo);
}
// otherwise get from db
self.findOne({id: id}, function (err, dbFoo) {
if (err || !dbFoo) {
return cb(new Error('Foo not found', 404));
// you could do get live call here
}
// and store in cache
cache.store('foo:' + id, dbFoo);
return cb(null, dbFoo);
});
});
};
Callers can then always just call Foo.get(id, callback) and they don't have to care how it is actually retrieved. If it gets more complicated, you could use an async library (such as the aptly named async) to make the code more readable, but this should still be completely hidden from the caller.

Resources