services_GeocodingService.js
import { RequestService } from '@ud-viz/utils_browser';
import { getAttributeByPath } from '@ud-viz/utils_shared';
export class GeocodingService {
/**
* Instantiates the geocoding service.
*
* @param {RequestService} requestService The request service.
* @param {import('itowns').Extent} extent The iTwons extent.
* @param {object} configGeocoding Geocoding config
*/
constructor(requestService, extent, configGeocoding) {
this.requestService = requestService;
this.extent = extent.as('EPSG:4326');
this.geocodingUrl = configGeocoding.url;
this.parameters = configGeocoding.parameters;
this.basePath = configGeocoding.basePath;
this.latPath = configGeocoding.result.lat;
this.lngPath = configGeocoding.result.lng;
this.credit = configGeocoding.credit;
this.requestTimeIntervalMs = configGeocoding.requestTimeIntervalMs;
this.canDoRequest = true;
}
/**
* Retrieves the coordinates based on the search string parameter.
*
* @param {string} searchString Either an address or the name of a place.
*/
async getCoordinates(searchString) {
if (!!this.requestTimeIntervalMs && !this.canDoRequest) {
throw 'Cannot perform a request for now.';
}
// URL parameters
const queryString = encodeURIComponent(searchString);
// Build the URL according to parameter description (in config file)
let url = this.geocodingUrl + '?';
for (const [paramName, param] of Object.entries(this.parameters)) {
if (param.fill === 'value') {
url += `${paramName}=${param.value}`;
} else if (param.fill === 'query') {
url += `${paramName}=${queryString}`;
} else if (param.fill === 'extent') {
url +=
paramName +
'=' +
param.format
.replace('SOUTH', this.extent.south)
.replace('WEST', this.extent.west)
.replace('NORTH', this.extent.north)
.replace('EAST', this.extent.east);
}
url += '&';
}
// Make the request
const req = await this.requestService.request('GET', url, {
authenticate: false,
});
const response = JSON.parse(req.response);
const results = (this.basePath ? response[this.basePath] : response).map(
(res) => {
return {
lat: Number(getAttributeByPath(res, this.latPath)),
lng: Number(getAttributeByPath(res, this.lngPath)),
};
}
);
if (this.requestTimeIntervalMs) {
this.canDoRequest = false;
setTimeout(() => {
this.canDoRequest = true;
}, Number(this.requestTimeIntervalMs));
}
if (results.length > 0) {
return results;
}
throw 'No result found';
}
}