I wrote this code for an personal application, just to help me visualize some data related to driving. I have one JSON on my machine, this JSON contains a set of locations (lat, lngs) and every location has a category (integer number).
After I fetch this file I want to use Google's Road API, to snap the points on the road. Unfortunately it only allows 100 points per request. And depending on the "track" I can have usually 400+ points.
At this point, this application is only maintained by me. But I used this as an excuse to re-learn Javascript (including the new stuff only new browsers have).
I used Promises and I was used to the callback hell of before and after reading so much good stuff about Promises I got really frustrated seeing this huge chaining I made.
It's working, can't complain about that. But, looks messy.
document.addEventListener('DOMContentLoaded', function(evt){
'use strict';
const apiKey = '-----------';
let rawMap = new google.maps.Map(document.getElementById('rawMap'), {
center: {lat: 0, lng: 0},
zoom: 10
});
let snappedMap = new google.maps.Map(document.getElementById('snappedMap'), {
center: {lat: 0, lng: 0},
zoom: 10
});
const colors = [
'#FF0000',
'#00FF00',
'#0000FF',
'#FFFF00',
'#00FFFF',
'#FF00FF',
'#000000',
];
fetch('output.json').then(response => response.json()).then(function(points){
for (let i = 0 ; i < points.length - 1 ; ++i) {
let path = new google.maps.Polyline({
path: [points[i], points[i+1]],
strokeColor: colors[points[i]['cat']],
strokeWeight: 5
});
path.setMap(rawMap);
}
let bounds = new google.maps.LatLngBounds();
points.forEach(point => bounds.extend(point));
rawMap.fitBounds(bounds)
snappedMap.fitBounds(bounds);
let requests = [];
for (let i = 0; i < points.length ; i += 100) {
let params = new URLSearchParams();
params.append('interpolate', 'true');
params.append('key', apiKey)
params.append('path', points.slice(i, i + 100).map(point => `${point['lat']},${point['lng']}`).join('|'));
requests.push(fetch(`https://roads.googleapis.com/v1/snapToRoads?${params}`));
}
return Promise.all(requests)
.then(responses => Promise.all(responses.map(response => response.json())))
.then(function(jsons){
for (let i = 0, lastIndex = -1; i < jsons.length ; ++i) {
let snappedPoints = jsons[i].snappedPoints;
for (let snappedPoint of snappedPoints) {
if ('originalIndex' in snappedPoint) {
lastIndex = i * 100 + snappedPoint.originalIndex;
}
snappedPoint['cat'] = points[lastIndex]['cat'];
}
}
return jsons;
});
}).then(function(jsons) {
return jsons.reduce((ret, json) => ret.concat(json.snappedPoints), [])
}).then(function(snappedPoints){
for (let i = 0; i < snappedPoints.length - 1; i++) {
let path = new google.maps.Polyline({
path: [
{
lat: snappedPoints[i].location.latitude,
lng: snappedPoints[i].location.longitude
},
{
lat: snappedPoints[i+1].location.latitude,
lng: snappedPoints[i+1].location.longitude
}
],
strokeWeight:5,
strokeColor: colors[snappedPoints[i]['cat']]
});
path.setMap(snappedMap);
}
}).catch(function(error){
console.log(error);
});
});