Update getData and httpRequest to modern TypeScript

This commit is contained in:
Matthew Oslan
2019-05-09 13:20:49 -04:00
parent 6acb40eed1
commit f2f40d2253

View File

@@ -14,16 +14,19 @@ var http = require( "http" ),
// If location does not match GPS or PWS/ICAO, then attempt to resolve // If location does not match GPS or PWS/ICAO, then attempt to resolve
// location using Weather Underground autocomplete API // location using Weather Underground autocomplete API
function resolveCoordinates( location, callback ) { async function resolveCoordinates( location, callback ) {
// Generate URL for autocomplete request // Generate URL for autocomplete request
var url = "http://autocomplete.wunderground.com/aq?h=0&query=" + var url = "http://autocomplete.wunderground.com/aq?h=0&query=" +
encodeURIComponent( location ); encodeURIComponent( location );
httpRequest( url, function( data ) { let data;
try {
// Parse the reply for JSON data data = await getData( url );
data = JSON.parse( data ); } catch (err) {
// If the request fails, indicate no data was found.
callback( false );
}
// Check if the data is valid // Check if the data is valid
if ( typeof data.RESULTS === "object" && data.RESULTS.length && data.RESULTS[ 0 ].tz !== "MISSING" ) { if ( typeof data.RESULTS === "object" && data.RESULTS.length && data.RESULTS[ 0 ].tz !== "MISSING" ) {
@@ -35,21 +38,22 @@ function resolveCoordinates( location, callback ) {
// Otherwise, indicate no data was found // Otherwise, indicate no data was found
callback( false ); callback( false );
} }
} );
} }
function getData( url, callback ) { /**
* Makes an HTTP GET request to the specified URL and parses the JSON response body.
httpRequest( url, function( data ) { * @param url The URL to fetch.
* @return A Promise that will be resolved the with parsed response body if the request succeeds, or will be rejected
* with an Error if the request or JSON parsing fails.
*/
async function getData( url: string ): Promise< any > {
try { try {
data = JSON.parse( data ); const data: string = await httpRequest(url);
return JSON.parse(data);
} catch (err) { } catch (err) {
callback( {} ); // Reject the promise if there was an error making the request or parsing the JSON.
return; throw err;
} }
callback( data );
return;
} );
} }
// Retrieve data from Open Weather Map for water level calculations // Retrieve data from Open Weather Map for water level calculations
@@ -57,11 +61,19 @@ function getOWMWateringData( location, callback ) {
var OWM_API_KEY = process.env.OWM_API_KEY, var OWM_API_KEY = process.env.OWM_API_KEY,
forecastUrl = "http://api.openweathermap.org/data/2.5/forecast?appid=" + OWM_API_KEY + "&units=imperial&lat=" + location[ 0 ] + "&lon=" + location[ 1 ]; forecastUrl = "http://api.openweathermap.org/data/2.5/forecast?appid=" + OWM_API_KEY + "&units=imperial&lat=" + location[ 0 ] + "&lon=" + location[ 1 ];
getTimeData( location, function( weather ) { getTimeData( location, async function( weather ) {
// Perform the HTTP request to retrieve the weather data // Perform the HTTP request to retrieve the weather data
getData( forecastUrl, function( forecast ) { let forecast;
try {
forecast = await getData( forecastUrl );
} catch (err) {
// Return just the time data if retrieving the forecast fails.
callback( weather );
return;
}
// Return just the time data if the forecast data is incomplete.
if ( !forecast || !forecast.list ) { if ( !forecast || !forecast.list ) {
callback( weather ); callback( weather );
return; return;
@@ -85,7 +97,6 @@ function getOWMWateringData( location, callback ) {
callback( weather ); callback( weather );
} ); } );
} );
} }
// Retrieve weather data from Open Weather Map for App // Retrieve weather data from Open Weather Map for App
@@ -94,12 +105,19 @@ function getOWMWeatherData( location, callback ) {
currentUrl = "http://api.openweathermap.org/data/2.5/weather?appid=" + OWM_API_KEY + "&units=imperial&lat=" + location[ 0 ] + "&lon=" + location[ 1 ], currentUrl = "http://api.openweathermap.org/data/2.5/weather?appid=" + OWM_API_KEY + "&units=imperial&lat=" + location[ 0 ] + "&lon=" + location[ 1 ],
forecastDailyUrl = "http://api.openweathermap.org/data/2.5/forecast/daily?appid=" + OWM_API_KEY + "&units=imperial&lat=" + location[ 0 ] + "&lon=" + location[ 1 ]; forecastDailyUrl = "http://api.openweathermap.org/data/2.5/forecast/daily?appid=" + OWM_API_KEY + "&units=imperial&lat=" + location[ 0 ] + "&lon=" + location[ 1 ];
getTimeData( location, function( weather ) { getTimeData( location, async function( weather ) {
getData( currentUrl, function( current ) { let current, forecast;
try {
getData( forecastDailyUrl, function( forecast ) { current = await getData( currentUrl );
forecast = await getData( forecastDailyUrl );
} catch (err) {
// Return just the time data if retrieving weather data fails.
callback( weather );
return;
}
// Return just the time data if the weather data is incomplete.
if ( !current || !current.main || !current.wind || !current.weather || !forecast || !forecast.list ) { if ( !current || !current.main || !current.wind || !current.weather || !forecast || !forecast.list ) {
callback( weather ); callback( weather );
return; return;
@@ -130,8 +148,6 @@ function getOWMWeatherData( location, callback ) {
callback( weather ); callback( weather );
} ); } );
} );
} );
} }
// Calculate timezone and sun rise/set information // Calculate timezone and sun rise/set information
@@ -386,33 +402,40 @@ exports.getWateringData = function( req, res ) {
} }
}; };
// Generic HTTP request handler that parses the URL and uses the /**
// native Node.js http module to perform the request * Makes an HTTP GET request to the specified URL and returns the response body.
function httpRequest( url, callback ) { * @param url The URL to fetch.
url = url.match( filters.url ); * @return A Promise that will be resolved the with response body if the request succeeds, or will be rejected with an
* Error if the request fails.
*/
async function httpRequest( url: string ): Promise< string > {
return new Promise< any >( ( resolve, reject ) => {
var options = { const splitUrl: string[] = url.match( filters.url );
host: url[ 1 ],
port: url[ 2 ] || 80, const options = {
path: url[ 3 ] host: splitUrl[ 1 ],
port: splitUrl[ 2 ] || 80,
path: splitUrl[ 3 ]
}; };
http.get( options, function( response ) { http.get( options, ( response ) => {
var data = ""; let data = "";
// Reassemble the data as it comes in // Reassemble the data as it comes in
response.on( "data", function( chunk ) { response.on( "data", ( chunk ) => {
data += chunk; data += chunk;
} ); } );
// Once the data is completely received, return it to the callback // Once the data is completely received, resolve the promise
response.on( "end", function() { response.on( "end", () => {
callback( data ); resolve( data );
} ); } );
} ).on( "error", function() { } ).on( "error", ( err ) => {
// If the HTTP request fails, return false // If the HTTP request fails, reject the promise
callback( false ); reject( err );
} );
} ); } );
} }