google maps | use Google Geocaching | extract depth maps | Search

This code efficiently retrieves geolocation data for a list of destinations, leveraging a cache to speed up subsequent requests and reduce API calls.

Run example

npm run import -- "cache locations nearby"

cache locations nearby

var fs = require('fs');
var unidecode = require('unidecode');
var importer = require('../Core');
var placesNearby = importer.import("places nearby api");

var PROFILE_PATH = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
var PROJECT_PATH = PROFILE_PATH + '/Collections/timeline';

var nearbyCache;
// cache resturants and locations that don't change often, saves geolocation api calls
try {
    nearbyCache = JSON.parse(fs.readFileSync(PROJECT_PATH + '/geolocations.json').toString());
} catch (e) {
    nearbyCache = {};
}

function getNearby(destinations) {
    return importer.runAllPromises(destinations
        .filter(d => !d.traveling)
        .map(d => resolve => {
            if (typeof nearbyCache[d.name + ', ' + d.location] !== 'undefined') {
                return resolve(nearbyCache[d.name + ', ' + d.location]);
            }
            console.log(d.name + ', ' + d.location);
            return placesNearby(
                unidecode(d.name + ', ' + d.location),
                {lat: d.averageLat, lng: d.averageLon})
                .then(result => {
                    if (result.length === 0) {
                        console.warn('No match for ' + JSON.stringify(d))
                        resolve();
                    } else {
                        nearbyCache[d.name + ', ' + d.location] = result[0];
                        resolve(Object.assign(d, result[0]))
                    }
                })
                .catch(e => resolve(e))
        }))
        .then(r => {
            fs.writeFileSync(
                PROJECT_PATH + '/geolocations.json',
                JSON.stringify(nearbyCache, null, 4));
            return r.filter(l => typeof l !== 'undefined');
        })
}
module.exports = getNearby;

What the code could have been:

const fs = require('fs').promises;
const unidecode = require('unidecode');
const importer = require('../Core');
const placesNearby = importer.import('places nearby api');

const PROFILE_PATH = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
const PROJECT_PATH = `${PROFILE_PATH}/Collections/timeline`;

let nearbyCache;
try {
    nearbyCache = JSON.parse(await fs.readFile(`${PROJECT_PATH}/geolocations.json`, 'utf8'));
} catch (e) {
    nearbyCache = {};
}

/**
 * Get nearby locations for destinations.
 * 
 * @param {Array} destinations - List of destinations with name and location.
 * @returns {Promise>} - List of destinations with nearby locations.
 */
async function getNearby(destinations) {
    const filteredDestinations = destinations.filter(d =>!d.traveling);
    const promises = filteredDestinations.map(async (d) => {
        // Check cache first
        const cacheKey = `${d.name}, ${d.location}`;
        if (nearbyCache[cacheKey]) {
            return nearbyCache[cacheKey];
        }
        console.log(`${d.name}, ${d.location}`);
        try {
            const result = await placesNearby(
                unidecode(`${d.name}, ${d.location}`),
                { lat: d.averageLat, lng: d.averageLon });
            if (result.length === 0) {
                console.warn(`No match for ${JSON.stringify(d)}`);
                return {};
            }
            nearbyCache[cacheKey] = result[0];
            return Object.assign(d, result[0]);
        } catch (e) {
            console.error(`Error for ${d.name}: ${e}`);
            return {};
        }
    });

    const results = await Promise.all(promises);
    // Write cache to file
    await fs.writeFile(`${PROJECT_PATH}/geolocations.json`, JSON.stringify(nearbyCache, null, 4));
    return results.filter(l => Object.keys(l).length > 0);
}

module.exports = getNearby;

This code fetches nearby places for a list of destinations, caching the results to improve performance.

Here's a breakdown:

  1. Dependencies:

    • fs: Node.js built-in module for file system operations.
    • unidecode: Library for converting Unicode characters to ASCII.
    • importer: Custom module likely responsible for importing other functions or modules.
    • placesNearby: Function imported from importer to fetch nearby places using the Google Places API.
  2. Configuration:

    • PROFILE_PATH: Path to the user's home directory.
    • PROJECT_PATH: Path to a directory where the code stores cached geolocation data.
    • nearbyCache: An object to store cached geolocation data. It's loaded from a JSON file if it exists, otherwise, it's initialized as an empty object.
  3. getNearby Function:

    • Takes an array of destinations as input, each destination having name, location, averageLat, and averageLon properties.
    • Filters out destinations marked as traveling.
    • Maps each remaining destination to a promise that:
      • Checks if the geolocation data is already cached. If so, it resolves with the cached data.
      • Otherwise, it calls placesNearby to fetch the geolocation data from the API.
      • If a match is found, it caches the result in nearbyCache and resolves with the destination object augmented with the geolocation data.
      • If no match is found, it logs a warning and resolves with undefined.
    • Uses importer.runAllPromises to execute all the promises concurrently.
    • Saves the updated nearbyCache to the JSON file.
    • Filters out undefined values from the results and returns the array of destinations with geolocation data.
  4. Export:

    • The getNearby function is exported as a module, making it available for use in other parts of the application.

Let me know if you have any other code snippets you'd like me to explain!