Reputation: 1456
I'm wanting to return a value in the main of my AWS function. I'm having trouble getting the data to pass from the first callback so I can send it to the final one.
/** module used for outbound http requests */
var request = require('request');
/** module used for parsing XML easily. https://www.npmjs.com/package/xml2js*/
var parseString = require('xml2js').parseString;
exports.handler = (event, context, callback) => {
// testing array of coordinates
var arrayOfPoints = [39.7683800, -86.1580400, 41.881832, -87.623177];
var results = getXMLFromNOAA(arrayOfPoints);
callback(null, results); // <- returns 'undefined' in the AWS console. I'm assuming race condition.
};
/**
* getXMLFromNOAA
*
* This is a function used for figuring out the functionality of NOAA XML parsing
*
* @param arrayOfPoints {Array[Double]} - An evenly numbered index array of latitudes and longitudes
*
* @return result {XML/JSON} - weather information abled to be parsed
*/
function getXMLFromNOAA(arrayOfPoints, callback) {
var baseURL = "http://graphical.weather.gov/xml/sample_products/browser_interface/ndfdXMLclient.php?whichClient=NDFDgenLatLonList&lat=&lon=&listLatLon=";
// for-loop getting all points and dynamically adding them to the query url string
// iterate 2 at a time since they are coupled coordinates (e.g. [lat1, lng1, lat2, lng2, ... latN, lngN])
for(var i = 0; i < arrayOfPoints.length; i = i + 2)
{
// if we're at the end of the arrayOfPoints, finish up the chain of query coordinates
if( (i+2) == arrayOfPoints.length)
{
baseURL = baseURL.concat(arrayOfPoints[i]);
baseURL = baseURL.concat("%2C");
baseURL = baseURL.concat(arrayOfPoints[i+1]);
}
else
{
baseURL = baseURL.concat(arrayOfPoints[i]);
baseURL = baseURL.concat("%2C");
baseURL = baseURL.concat(arrayOfPoints[i+1]);
baseURL = baseURL.concat("+");
}
}
// TIME
baseURL = baseURL.concat("&lat1=&lon1=&lat2=&lon2=&resolutionSub=&listLat1=&listLon1=&listLat2=&listLon2=&resolutionList=&endPoint1Lat=&endPoint1Lon=&endPoint2Lat=&endPoint2Lon=&listEndPoint1Lat=&listEndPoint1Lon=&listEndPoint2Lat=&listEndPoint2Lon=&zipCodeList=&listZipCodeList=¢erPointLat=¢erPointLon=&distanceLat=&distanceLon=&resolutionSquare=&listCenterPointLat=&listCenterPointLon=&listDistanceLat=&listDistanceLon=&listResolutionSquare=&citiesLevel=&listCitiesLevel=§or=&gmlListLatLon=&featureType=&requestedTime=&startTime=&endTime=&compType=&propertyName=&product=time-series&begin=2016-09-04T00:00:00&end=2016-09-11T00:00:00");
// CHARACTERISTICS REQUESTED
// http://graphical.weather.gov/xml/docs/elementInputNames.php
baseURL = baseURL.concat("&Unit=e&maxt=maxt&mint=mint&temp=temp&appt=appt&rh=rh&sky=sky&wwa=wwa&iceaccum=iceaccum&ptornado=ptornado&phail=phail&ptstmwinds=ptstmwinds&pxtornado=pxtornado&pxhail=pxhail&ptotsvrtstm=ptotsvrtstm&wgust=wgust");
// Used for testing and seeing the final result
console.log(baseURL);
request(baseURL, function (error, response, body)
{
if (!error && response.statusCode == 200)
{
parseString(body, function (err, result) {
console.log('inside parseString: ' + result); // <- this prints but it won't show up in the main
// callback(null, result); <- doesnt work
return result; // doesnt work either
});
}
})
}
I want to be able to make my code more modular for scalability. I know theres a way to take the async process of the getXMlFromNOAA
and perform them iteratively. I'm just not as familiar with JavaScript as I should be. Any help would really be appreciated.
Upvotes: 0
Views: 84
Reputation: 6377
Thats not how callbacks work. Change the handler to something like this:
exports.handler = (event, context, callback) => {
var arrayOfPoints = [39.7683800, -86.1580400, 41.881832, -87.623177];
getXMLFromNOAA(arrayOfPoints, function(result) {
console.log('returned');
console.log(result);
callback(null, result);
});
};
Also uncomment (go back) to the callback(result)
in getXMLFromNOAA
;
Also for NOAA there is a module. Always search node-modules/npmjs.com/npms.io first before reinventing the wheel. The example here https://github.com/thataustin/noaa-forecasts is very similar to what you are doing so I would start with that.
If you want to simplify async stuff in the future you can use babel
with async
and await
keywords. But you will need to make sure you really learn callbacks and promises first.
Upvotes: 0
Reputation: 6232
You can use async module to make it more readable and flexible and also free from the asynchronous issue. Write your stuff something like this
/** module used for outbound http requests */
var request = require('request');
var async = require('async');
/** module used for parsing XML easily. https://www.npmjs.com/package/xml2js*/
var parseString = require('xml2js').parseString;
exports.handler = (event, context, callback) => {
async.waterfall([
function(next) {
// testing array of coordinates
var arrayOfPoints = [39.7683800, -86.1580400, 41.881832, -87.623177];
var results = getXMLFromNOAA(arrayOfPoints, next);
},
function(baseURL, next) {
request(baseURL, function(error, response, body) {
if (!error && response.statusCode == 200) {
parseString(body, function(err, result) {
console.log('inside parseString: ' + result); // <- this prints but it won't show up in the main
if (!err)
next(null, result);
});
}
})
}
], function(err, result) {
if (!err) {
callback(null, results); // <- returns 'undefined' in the AWS console. I'm assuming race condition.
}
})
};
/**
* getXMLFromNOAA
*
* This is a function used for figuring out the functionality of NOAA XML parsing
*
* @param arrayOfPoints {Array[Double]} - An evenly numbered index array of latitudes and longitudes
*
* @return result {XML/JSON} - weather information abled to be parsed
*/
function getXMLFromNOAA(arrayOfPoints, next) {
var baseURL = "http://graphical.weather.gov/xml/sample_products/browser_interface/ndfdXMLclient.php?whichClient=NDFDgenLatLonList&lat=&lon=&listLatLon=";
// for-loop getting all points and dynamically adding them to the query url string
// iterate 2 at a time since they are coupled coordinates (e.g. [lat1, lng1, lat2, lng2, ... latN, lngN])
for (var i = 0; i < arrayOfPoints.length; i = i + 2) {
// if we're at the end of the arrayOfPoints, finish up the chain of query coordinates
if ((i + 2) == arrayOfPoints.length) {
baseURL = baseURL.concat(arrayOfPoints[i]);
baseURL = baseURL.concat("%2C");
baseURL = baseURL.concat(arrayOfPoints[i + 1]);
} else {
baseURL = baseURL.concat(arrayOfPoints[i]);
baseURL = baseURL.concat("%2C");
baseURL = baseURL.concat(arrayOfPoints[i + 1]);
baseURL = baseURL.concat("+");
}
}
// TIME
baseURL = baseURL.concat("&lat1=&lon1=&lat2=&lon2=&resolutionSub=&listLat1=&listLon1=&listLat2=&listLon2=&resolutionList=&endPoint1Lat=&endPoint1Lon=&endPoint2Lat=&endPoint2Lon=&listEndPoint1Lat=&listEndPoint1Lon=&listEndPoint2Lat=&listEndPoint2Lon=&zipCodeList=&listZipCodeList=¢erPointLat=¢erPointLon=&distanceLat=&distanceLon=&resolutionSquare=&listCenterPointLat=&listCenterPointLon=&listDistanceLat=&listDistanceLon=&listResolutionSquare=&citiesLevel=&listCitiesLevel=§or=&gmlListLatLon=&featureType=&requestedTime=&startTime=&endTime=&compType=&propertyName=&product=time-series&begin=2016-09-04T00:00:00&end=2016-09-11T00:00:00");
// CHARACTERISTICS REQUESTED
// http://graphical.weather.gov/xml/docs/elementInputNames.php
baseURL = baseURL.concat("&Unit=e&maxt=maxt&mint=mint&temp=temp&appt=appt&rh=rh&sky=sky&wwa=wwa&iceaccum=iceaccum&ptornado=ptornado&phail=phail&ptstmwinds=ptstmwinds&pxtornado=pxtornado&pxhail=pxhail&ptotsvrtstm=ptotsvrtstm&wgust=wgust");
// Used for testing and seeing the final result
console.log(baseURL);
//retun to callback after getting URL
next(null, baseURL)
}
Upvotes: 2