My controller is a soap client as shown below
var _ = require('lodash'),
memoize = require('memoize'),
soap = require('soap'),
http = require('http');
var wsdlUrl = 'http://www.proxixnetwork.com/gsert/PxPointGeocode.asmx?WSDL';
var geocode = function(req,res){
var sessionId = null;
soap.createClient(wsdlUrl, function(err,client){
var args = {"username":'user123', "password":'password123'};
client.PxPointGeocode.PxPointGeocodeSoap.Authenticate(args,function(err,result){
res.jsonp(result.AuthenticateResult.SessionID);
})
});
}
exports.authenticate = geocode;
This soap service provides a session id that will be used in subsequent requests. Hence, I wanted to use 'memoize' to cache the method.
I defined a method that wraps around the soap call and 'memoize'ing it but the problem is that the call to soapClient is not happening.
I do not know how to make the call from router wait for the soap call
Note: Also tried async library's waterfall but did not work.
var _ = require('lodash'),
memoize = require('memoize'),
soap = require('soap'),
http = require('http'),
wsdlUrl = 'http://www.proxixnetwork.com/gsert/PxPointGeocode.asmx?WSDL';
var getSession = function () {
var args = {"username": 'user123', "password": 'password123'};
var sessionId = null;
soap.createClient(wsdlUrl, function (err, client) {
console.log('Inside proxix client'); //not printing
client.PxPointGeocode.PxPointGeocodeSoap.Authenticate(args, function (err, result) {
sessionId= result.AuthenticateResult.SessionID;
//if I use res.jsonp() - the call could be made
})
});
return sessionId;
};
var cached = memoize(getSession);
var geocode = function (req, res) {
var sesssionObj = cached();
res.jsonp(sessionObj);
}
exports.authenticate = geocode;
The two issues I'm seeing are :
memoize is a caching mechanism but is in no way going to change the ansynchronous nature of your function. Returning sessionId will not work because it is not set before it gets to that line. You need to use a callback.
You have not specified which arguments you want memoize to use for the caching, nor where you are getting those values. I'm going to assume for this example that it's username, password and wsdlUrl. and that they are set directly in req.
.
var _ = require('lodash'),
memoize = require('memoize'),
soap = require('soap'),
http = require('http');
var getSessionId = function(username,password,wsdlUrl,callback){
soap.createClient(wsdlUrl, function(err,client){
var args = {"username":username, "password":password};
client.PxPointGeocode.PxPointGeocodeSoap.Authenticate(args,function(err,result){
if(err){
return callback(err);
}
callback(null,result.AuthenticateResult.SessionID);
})
});
});
var getSessionIdCached = memoize(getSessionId,{async:true});
var geocode = function(req,res){
getSessionIdCached(req.username,req.password,req.wsdlUrl,function(err,sessionId){
if(err){
//do some error handling, and probably return
}
res.jsonp(sessionId);
});
});
exports.authenticate = geocode;
Related
I am trying to retrieve a var hash to use it in another module. But I have a problem with callback. I have the error "callback is not a function". I use callback because my variable hash is undefined, so I guess it's a problem of asynchronous.
hash.js
var fs = require('fs');
var crypto = require('crypto');
var algorithm = 'sha256';
var hash = function(filename, callback){
var shasum = crypto.createHash(algorithm);
var s = fs.ReadStream(filename);
s.on('data', function(data) {
shasum.update(data)
})
s.on('end', function() {
var hash = shasum.digest('hex')
callback(hash);
})
}
exports.hash = hash;
app.js
app.post('/upload', upload.single('userfile'), function(req, res){
res.cookie('filename', req.file.originalname);
res.cookie('filesize', req.file.size);
var filename = __dirname +'/'+ req.file.path;
console.log(hash.hash(filename))
//res.cookie('hash', hash.hash(filename));
res.redirect('/hash')
})
Your hash() function is defined with this signature:
var hash = function(filename, callback)
That means you need to pass it BOTH a filename and a callback. But, you are passing it only a filename:
console.log(hash.hash(filename))
As you can see in the implementation, the callback is not optional and is the only way to actually get the result like this:
hash.hash(filename, function(result) {
console.log(result);
});
This question already has answers here:
How do I convert an existing callback API to promises?
(24 answers)
Closed 6 years ago.
MY ACTUAL CODE (THAT WORKS!)
I've created a function with callback to create sessions and generate tokens for OpenTok, that exports itself to application.
The function
//Dependencies
var opentok = require('./ot').opentok;
var apiKey = require('./ot').apiKey;
var apiSecret = require('./ot').apiSecret;
//Define variables
var sessionId;
var token;
//Define create newSession function
var newSession = function(callbackS){
//Create Session (That allows to OpenTok)
opentok.createSession({mediaMode:"relayed"}, function(err, session){
if(err) throw err;
else {
//Define session object
var objSession = {};
//Obtain sessionId
objSession.sessionId = session.sessionId;
//Call generate token function
newTok(objSession,callbackS);
}
});
}
//Define generate token function
var newTok = function(obj, fn){
//Generate token (that allows to OpenTok)
token = opentok.generateToken(obj.sessionId);
//Store object (obj.tokenId) in token variable
obj.tokenId = token;
//Define "obj" in function context
fn(obj);
}
//Export new Session with sessionId and token
module.exports.credentials = newSession;
The APP
// Dependencies
var express = require('express');
var server_port = process.env.PORT || 3000;
var apiKey = require('./ot').apiKey; //Obtain default apiKey
var credentials = require('./credentials').credentials(fun);
//function that was export from "credentials" (the function)
function fun(obj) {
//Define app
var app = express();
//Use "public" static folder
app.use(express.static(__dirname + '/public'));
//Initialize the app
init();
//Routing
app.get('/', function(req, res) {
//Rendering variables in views
res.render('index.ejs', {
apiKey: apiKey,
sessionId: obj.sessionId,
token: obj.tokenId
});
});
//Define Init
function init() {
app.listen(server_port, function() {
console.log('The app is running in localhost:' + server_port);
});
}
}
THAT I WANT:
How I could convert my function that creates sessions and generates tokens in a promise that I can use into my app?
UPDATE (08/01/2016) (14:53 VET)
I've exported the function module in my app as follow:
// Dependencies
var express = require('express');
var server_port = process.env.PORT || 3000;
var apiKey = require('./ot').apiKey; //Obtain default apiKey
var credentialsPromise = require('./credentialsPromise').credentialsPromise(); //Obtain the promise
console.log(credentialsPromise);
And throw in console:
Promise { <pending> }
How I should use my promise in my app?
The minimal approach is as follows (see *** comments):
var newSession = function(){
// *** Return a promise
return new Promsie(function(resolve, reject) {
opentok.createSession({mediaMode:"relayed"}, function(err, session){
// *** Reject on error
if (err) {
reject(err);
} else {
var objSession = {};
objSession.sessionId = session.sessionId;
// *** Have newTok call `resolve` with the object when done
newTok(objSession, resolve);
}
});
});
};
Note that I didn't promise-ify newTok, though we could. It's not clear why newTok accepts a callback when nothing in it is asynchronous and it's a private function.
Using it looks like this:
newSession(/*...parameters...*/).then(
function(result) {
// All is good, use result
},
function(err) {
// Error occurred, see `err`
}
);
I'm calling the function getKeywords from another function and got an Unrecheable code detected section and don't understand why. Any help?
var env = require('dotenv').config();
var request = require('request')
var getKeywords = function(){
request.get('URI', //URI IS CORRECT IN MY CODE
function(err, httpResponse, body){
if(err){ //UNREACHABLE CODE DETECTED
console.error("request.post Error:", err);
return false;
} //UNREACHABLE CODE DETECTED
else{
console.log('Im here');
return JSON.parse(httpResponse.body).keywords;
}
});
}
module.export = getKeywords;
Here is the calling code.
var getKeywords = require('./getKeywords.js');
var keywords = new getKeywords();
var env = require('dotenv').config();
var difflib = require('difflib');
var postMention = require('./postMention.js');
var detection = function(obj, i){
var keyword = keywords[i];
var mentionObject = {
//some json
//postMention(mentionObject);
}
}
module.exports = detection;
Some tools have the ability to analyze every call to your function. It may be possible that all the places in your code that call the function you never set err parameter to true.
What am I doing wrong in the code below? The left_label and right_label variables seem to always be "true", when I know I have them in the Redis set to some string. I'm assuming it's because the client.get function is successful and returns true, but how do I get it to return the actual value?
var http = require('http');
var redis = require('redis');
var client = redis.createClient(6379, 127.0.0.1);
var server = http.createServer(function (request, response) {
var left_label = client.get('left', function(err, reply) {
console.log(reply);
return reply;
});
var right_label = client.get('right', function(err, reply) {
console.log(reply);
return reply;
});
response.writeHead(200, {"Content-Type": "text/html"});
var swig = require('swig');
var html = swig.renderFile('/var/www/nodejs/index.html', {
left: left_label,
right: right_label
});
response.end(html);
});
server.listen(8000);
console.log("Server running at http://127.0.0.1:8000/");
The get call is asynchronous and must be handled that way.
A suggestion would be to combine it with a promise library such as bluebird as suggested in the NPM documentation for the redis module.
That way, we can promisify the redis module and use it in a more simple way.
var redis = require('redis');
bluebird.promisifyAll(redis.RedisClient.prototype);
and use the new async version of the get function, as below.
function getLabelValues(){
var left_promise = client.getAsync("left").then(function(reply) {
return reply;
});
var right_promise = client.getAsync("right").then(function(reply) {
return reply;
});
return Promise.all([left_label, right_label]);
}
getLabelValues().then(function(results){
//This is run when the promises are resolved
//access the return data like below
var left_label = results[0];
var right_label = results[1];
});
I have 3 node js files :
mysqlconnection.js to store the database connection properties:
var mysql = require('mysql');
var cjson = require('cjson');
var yaml_config = require('node-yaml-config');
// project files
var config = yaml_config.load(__dirname + '/billingv2.yaml');
exports.execute = function(callback){
var connection = mysql.createConnection(
{
host : config.host,
user : config.user,
password : config.password,
database : config.database,
}
);
connection.connect();
return callback(null,connection);
}
subscriptionRestService.js to handle the REST api calls:
var express = require('express');
var app = express();
app.use(express.bodyParser());
var fs = require('fs');
// Project files
var mysql = require('./mysqlRestService.js');
// Get Resource Subscription data by Resourceuri
app.post('/pricingdetails', function(req, res) {
var workload = req.body;
if(workload.elements && workload.elements.length > 0)
{
var arr = [];
for(var index in workload.elements)
{
arr[index] = workload.elements[index].uri;
}
var resourceIdentifiers = arr.join(',');
}
console.log(resourceIdentifiers);
mysql.getPricingDetail(function(resourceIdentifiers,callback){
});
});
mysqlRestService.js to handle mysql queries/stored procedures:
// packages
var mysql = require('mysql');
var cjson = require('cjson');
var fs = require('fs');
var yaml_config = require('node-yaml-config');
// project files
var dbconnection = require('./mysqlconnection');
exports.getPricingDetail = function (resourceIdentifiers,callback){
console.log('entered into mysql function');
console.log(resourceIdentifiers);
var pricingDetail = {};
dbconnection.execute(function(err,response){
if(err){
throw err;
}
else
{
var selectqueryString = "call SP_ExposePricingDetailforUI('" + resourceIdentifiers + "')";
response.query(selectqueryString, function(err,pricingDetail){
if(err) {
throw err;
}
else
{
console.log(pricingDetail);
pricingDetail = pricingDetail;
}
});
}
});
//console.log('printing pricing details');
//console.log(pricingDetail);
};
problems faced
Unable to send the variable resourceIdentifiers from subscriptionRestService to mysqlRestService.js
Unable to return the pricingdetail from mysqlRestService.js to calling function in subscriptionRestService.
Any guidance greatly appreciated.
Unable to send the variable resourceIdentifiers from subscriptionRestService to mysqlRestService.js
Well, you didn't send it. It currently is a parameter of your callback function in the invocation, not an argument for the parameter of getPricingDetails. Use
mysql.getPricingDetail(resourceIdentifiers, function callback(result){
// use result here
});
Unable to return the pricingdetail from mysqlRestService.js to calling function in subscriptionRestService.
I've got no idea what pricingDetail = pricingDetail; was supposed to do. You have to call (invoke) back the callback here! Use
callback(pricingDetail);