Node.js param not being passed to callback function - node.js

I am creating a Alexa skill (Lambda function) node.js - And I am having having an issue passing in the "zipcode" const to the getLocation callback function, if i output the zipcode it will work.
The getLocation function it's not returning anything, and I am guessing it's because the zipcode param is not being passed in properly into the function.
There is nothing wrong with the function because if i replace the
var url = "localhost/api.php?zip="+zipcode;
with
var url = "localhost/api.php?zip=41242"; or any zip code it works.
What am i doing wrong?
let zipcode = request.intent.slots.zipcode.value;
getLocation(function(location, err) {
if(err) {
context.fail(err);
} else {
options.speechText += location.distance + " miles away,
You can get there by going to " + location.street_address + " in " + location.city + ", " + location.state;
options.endSession = true;
context.succeed(buildResponse(options));
}
});
function getLocation(callback, zipcode) {
var url = "localhost/api.php?zip="+zipcode;
var req = http.get(url, function(res) {
var body = "";
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
body = body.replace(/\\/g, '');
var location = JSON.parse(body);
callback(location);
});
res.on('error', function(err) {
callback('', err);
});
});
}

In the getLocation() function you should pass the zipcode as the second argument . your code will be something like this:
getLocation(function(location, err) {
*/you code here /*
} , zipcode);

Related

How do I await a nodejs request-promise object

I'm trying to return the results of an http request from a function and thought request-promise was supposed to return after an await. I obviously don't have this right. I get "undefined" returned from the function.
var s = getUrl();
console.log('result: ' + s)
function getUrl() {
var rp = require('request-promise');
var url = 'http://myserver.com?param=xxx';
rp(url)
.then(function (data) {
return data;
})
.catch(function (err) {
console.log(err);
});
}
How do I await the call so getUrl returns the data?
EDIT: After Kevin's comment. I tried to put this into a module and call it but it's returning [object Promise].
function getUrl(url, params) {
var rp = require('request-promise');
return rp(url + '?' + params)
.then(function (data) {
return data;
})
.catch(function (err) {
console.log(err);
});
}
async function getUpdate(o) {
var url = 'http://myserver.com';
var params = 'param=xxx';
var s = await getUrl(url, params);
return s;
}
exports.askVelo = (o) => {
var sRtn = '';
console.log(o.code);
switch (o.code) {
case 'g':
sRtn = getUpdate(o);
break;
}
console.log('heres rtn: ' + sRtn); // sRtn is [object Promise]
return sRtn;
}
getUpdate is now just returning [object Promise]... Why is that not working now?
I really needed to get the data in a synchronous fashion, so I finally gave up and used sync-request and skipped all the await/promise stuff.
sr = require('sync-request');
var url = 'http://myserver';
var qstring = 'param=xxx';
var res = sr('GET', url + '?' + qstring);
var str = res.body.toString();

Dialogflow Node.js is not getting the value of the https.get inside app.inent

I am having trouble getting the value returned by my https.get function inside the my Dialogflow intent to close the conversation. Regardless whether I execute this call in the app.intent or pass it one to an external function, it fails. I new to node.js but have used angular.js and javascript before but not having success in being able to close the conversation with a response. Google Actions emulator gives me the error
MalformedResponse
expected_inputs[0].input_prompt.rich_initial_prompt: 'rich_response'
must contain at least one item.
Below is my code:
app.intent('mywebhook', (conv, params) => {
const stateName = params['geo-state-us'];
console.log("My State is " + stateName);
var pathString = 'api path' + encodeURIComponent(stateName);
var request = https.get({
host: 'www.mydomainame.com',
path: pathString
}, function (response){
var json = "";
response.on('data', function(chunk) {
json += chunk;
});
response.on('end', function(){
var jsonData = JSON.parse(json);
var myfirstvar = jsonData[0].firstvar;
var chat = "the value of first var is " + chat;
console.log(chat); // this works fine
conv.close(chat);
});
}).on('error', (e) => {
console.error(e);
});
}
I even tried doing conv.close(chat) outside and JSON.stringify(request) to get the value of myfirstvar but nothing worked. Spent a whole day trying different things but no avail.
Try the refactored code below ( and comment if that works or not ):
app.intent('mywebhook', myWebHookFunction);
function myWebHookFunction(conv, params) {
return new Promise(function (resolve, reject) {
const stateName = params['geo-state-us'];
console.log("My State is " + stateName);
var pathString = 'api path' + encodeURIComponent(stateName);
var request = https.get({
host: 'www.mydomainame.com',
path: pathString
}, function (response) {
var json = "";
response.on('data', function (chunk) {
json += chunk;
});
response.on('end', function () {
var jsonData = JSON.parse(json);
var myfirstvar = jsonData[0].firstvar;
var chat = "the value of first var is " + chat; // chat or myfirstvar?
console.log(chat); // this works fine
conv.close(chat);
resolve();
});
}).on('error', (e) => {
console.error(e);
reject();
});
});
}

multiple http get calls nodejs

Thanks for looking into the code.
Here I am fetching some data using feed parser and taking out id's in navcodes array variable and wants to use these Id to make http call.Please find code below.
function processNavCode(){
var mfId = [53];
var preTitle = '';
var navCodes = [];
mfId.forEach(function(id){
var query = "http://portal.xyz.com/Rss.aspx?mf="+id;
feed(query, function(err, feeds) {
if (err) {
throw err;
}
feeds.forEach(function(feed){
var link = feed.link;
var title = feed.title;
var navCode = link.substr(link.length - 6);
if(title.split('-')[0].trim() != preTitle){
preTitle = title;
counter ++;
}
if(parseInt(navCode) != '')
navCodes.push = parseInt(navCode);
});
});
async.eachSeries(navCodes,insertbulkMFValues,function(){
console.log('I am done');
});
// insertbulkMFValues(navCode);
//Directly call insertbulkMFValues function
});
}
I have also tried to call the insertbulkMFValues directly as commented now but due to async nature of nodejs, I am getting the error of either 'Socket hang up' or 'read ECONNRESET'. I checked and used async but not able to work with that also.
var insertbulkMFValues =function(navCode,callback){
var options = {
host: 'www.quandl.com',
path: '/api/v3/datasets/AMFI/'+navCode+'.json?api_key=123456789&start_date=2013-08-30',
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}
var req1 = https.request(options, function(response) {
var body = '';
response.setEncoding('utf8');
response.on('data', function(chunk) {
body += chunk;
});
response.on('end', function() {
if(typeof body === "string") {
var json = JSON.parse(body);
}
var mfData = json.dataset.data;
var schemeId = json.dataset.dataset_code;
var schemeName = json.dataset.name;
var isinCode = json.dataset.description;
var valueData=[];
for (var k = 0; k < mfData.length; k++) {
var myDate = new Date(mfData[k][0]);
valueData.push({
date:myDate,
NAV:parseFloat(mfData[k][1]).toFixed(2)
});
}
var query = { "navCode": schemeId };
var newData = {
createdDate: Date.now(),
navCode: schemeId,
schemeCode:count,
schemeName:schemeName,
ISINCode:isinCode,
values:valueData
};
MHistory.findOneAndUpdate(query, newData , {upsert:true}, function(err, doc){
if(err)
console.log('Errorr');
else
console.log('Success');
});
});
});
req1.on('error', function(e) {
console.log('problem with request: ' + e.message);
callback(true);
});
req1.end();
}
Thanks in advance..
J
You can directly call insertbulkMFValues for each navCode like:
if(parseInt(navCode) != '') {
insertbulkMFValues(navCode, function () {
console.log('something'}
});
}
Anything that you intend to do must be within the callback of the asynchronous function.
One option for you is to use the waterfall or parallel method of the async library to retrieve all feeds for each id and then invoke
async.eachSeries(navCodesAccumulated,insertbulkMFValues,function(){
console.log('I am done');
});
within the final result callback using the codes obtained.

Nodejs/Async: How does callback work in iteratee function for async.map as mentioned in code snippet

Being new to nodejs ans async following is the code that I came across.
app = express();
/*
other express use calls like - app.use(bodyParser.json());
*/
var async = require("async");
var server;
app.post('/callType/call', function(req, res) {
var startTime = Date.now();
server = req.body.server;
//async.map asynchronuously call enrollStep1 for every element in the req.body.nodes array
//HOW DOES THIS WORK??!! - WHERE IS THE CALLBACK DEFINED OR SOURCED FROM???
//******************************************************
async.map(req.body.nodes, function(node, callback) {
someFunc(node.property1,node.property2,callback)
},
//This function is called when every task triggered by async.map has called its callback.
function(err, results) {
var response = {};
if (err) {
response.success = false;
response.error = err;
console.log("ERROR returned: " + JSON.stringify(response));
res.json(response);
} else {
var returnResults = [];
//Results is an array of array - flatten it
var flattenedResults = [].concat.apply([], results);
//then remove duplicates
for (var i = 0; i < flattenedResults.length; i++){
var obj = flattenedResults[i];
var isDup = returnResults.some(function(element) {
return element.tid === obj.tid;
});
if (!isDup) {
returnResults.push(obj);
}
}
response.success = true;
response.results = returnResults;
res.json(response);
}
});
});
function someFunc(property1, property2, callback) {
var url = '/'+callTypes +'/'+ call +'/'+ property1 +'/'+ property2
urClient
.get(server + url)
.header('Content-Type', 'application/json')
.end(
function(response) {
if (response.code !== 200) {
callback("Error " + ". Code: " + response.code + " Response: " + JSON.stringify(response));
} else {
callback("Success " + ". Code: " + response.code + " Response: " + JSON.stringify(response));
}
}
);
}
The iteratee function for async.map has a definition starting function(node, callback) { but the callback function is never assigned. How does the callback work over here.
Isn't it supposed to be assigned somewhere like callback = myCallbackFunction;
The async.map takes 3 arguments, the array/object, the function to map the data and the callback function, so your code should be:
async.map(req.body.nodes, someFunc , function(err, results) {
if (err) return console.log(err);
console.log(results);
});
And your someFunc should be:
function someFunc(item, callback) {
// do something with item
// it's each item in the original array/object
callback('The results');
}
This is a basic example: http://code.runnable.com/UyR-6c2DZZ4SmfSh/async-map-example-for-node-js

NODE.JS function callback to render page

I have a function getthem() that checks a mongo db for listings and returns name,streamurl for it.
I pass those as var stream to the renderme that renders the /dashboard page.
My problem is that i get the console.log("END OF FIND:"+JSON.stringify(stream))
to show my test input, but nothing goes to the render.
im using ejs to render. How can i get the result passed to the page ?
router.get('/dashboard', function (req, res) {
var foo = getthem();
function getthem() {
var group = "tesint";
console.log('geting for group : ' + group);
var mdlListings = require('../models/listings.js');
var myresult = "tet";
mdlListings.find({}, "name streamurl", function (err, data) {
if (err) {
console.error(err);
return;
}
if (data === null) {
console.log("No results");
return;
}
var stream = { };
data.forEach(function (streams) {
console.log("Got " + streams.name + " " + streams.streamurl);
stream[streams.name] = streams.streamurl;
// stream += 'name: '+streams.name+'},{streamurl: '+streams.streamurl;
// console.log("stram arry "+stream[streams.name] )
console.log("END OF FIND:"+JSON.stringify(stream))
}, renderme(stream));
// console.log("Result:", votes);
//var myresult = Object.keys(stream).map(function (name) {
// return { name: name, url: stream[name] };
//})
console.log("before return stream "+stream);
return stream;
});
}
function renderme(resa) {
console.log("RESA"+JSON.stringify(resa))
var resa = JSON.stringify(resa);
res.render('dashboard', {
title: 'Dashboard',
user: req.user,
listing: resa
}
)
}
You're passing the result of renderme(stream) as a second argument to forEach(). renderme(stream) is then evaluated immediately before your forEach() callback is called, when stream is still an empty object. My guess is you want something like this:
data.forEach(function (streams) {
console.log("Got " + streams.name + " " + streams.streamurl);
stream[streams.name] = streams.streamurl;
console.log("END OF FIND:"+JSON.stringify(stream))
});
renderme(stream);
Actually i figure that why would i pass the function as i could just do whatever i need to directly in there.
That worked perfectly, thanks for the tip.
data.forEach(function (streams) {
console.log("Got " + streams.name + " " + streams.streamurl);
stream[streams.name] = streams.streamurl;
});
res.render('dashboard', {
title: 'Dashboard',
user: req.user,
listing: data
}
)

Resources