Это немного вопрос с некоторым уровнем детализации, поэтому позвольте мне сначала объяснить ситуацию, затем мою реализацию и последний вопрос, чтобы вы лучше поняли.Неверный ответ службы сервиса «Карты Google» при расщеплении слишком большого пути
По состоянию на 4 апреля добавлено обновление и проблемы сужены до одной незавершенной проблемы, см. Нижнюю часть этого вопроса для актуальной информации.
TLDR;
У меня есть длинный маршрут, возвращаемый API Google Maps Directions и требующий диаграмму высоты для этого маршрута. Слишком плохо, что он не работает, потому что он запрашивается через GET, а максимальная длина URL - 2.048 символов, которые превышают. Я разделил запросы; гарантировал правильный порядок обработки, используя Promises; но данные Evelation не всегда полны для полного маршрута, не всегда отображаются в правильном порядке, не всегда следуют заданному пути, а местоположение промежуточной высоты занимает иногда несколько километров.
Введение;
Пытается создать диаграмму высот для ответа на Google Maps DirectionsService. Я столкнулся с проблемой слишком длинных маршрутов (это, похоже, не связано с расстоянием, а не с числом LatLngs за просмотр_просмотра). Это связано с тем, что ElevationService запрашивается через GET
, а максимальная длина URL - 2048 символов. Эта проблема - described on SO here as well.
Реализация;
Я полагал, что я умнее, чем Google (не очень, но, по крайней мере, пытаюсь найти способ работать вокруг него), чтобы разделить путь, возвращаемый DirectionsService (overview_path
собственности) в партии и сцепить результаты (elevations
, возвращенный методом ElevationService getElevationsAlongPath
).
- Чтобы получить наилучший уровень детализации, я запрашиваю ElevationService с 512 сэмплами за партию;
- и потому, что ElevationService распространяется на образцах по длине пути я создал максимальное количество
LatLng
на замес и проверить сколько партий требуются для обработки полного пути (totalBatches = overview_path.length/maxBatchSize
); - и, наконец, получить равномерное распределение по моим направлениям, приведет к попытке , чтобы получить равный уровень детализации для всего маршрута (
batchSize = Math.ceil(overview_path.length/totalBatches)
).
В то время как ElevationService работает асинхронно, я проверяю, что все запросы обрабатываются в правильном порядке с помощью других SO-пользователей, сначала используя setTimout и теперь работает с Promises.
Мой код
var maxBatchSize = 200;
var currentBatch = 0;
var promise = Promise.resolve();
var totalElevationBatches = Math.ceil(directions.routes[0].overview_path.length/maxBatchSize);
var batchSize = Math.ceil(directions.routes[0].overview_path.length/totalElevationBatches);
while(currentBatch < totalElevationBatches) {
promise = addToChain(promise, currentBatch, batchSize);
currentBatch++;
}
promise.then(function() {
drawRouteElevationChart(); // this uses the routeElevations to draw an AreaChart
});
function getRouteElevationChartDataBatchPromise(batch, batchSize) {
return new Promise(function(resolve, reject) {
var elevator = new google.maps.ElevationService();
var thisBatchPath = [];
for (var j = batch * batchSize; j < batch * batchSize + batchSize; j++) {
if (j < directions.routes[0].overview_path.length) {
thisBatchPath.push(directions.routes[0].overview_path[j]);
} else {
break;
}
}
elevator.getElevationAlongPath({
path: thisBatchPath,
samples: 512
}, function (elevations, status) {
if (status != google.maps.ElevationStatus.OK) {
if(status == google.maps.ElevationStatus.OVER_QUERY_LIMIT) {
console.log('Over query limit, retrying in 250ms');
resolve(setTimeout(function() {
getRouteElevationChartDataBatchPromise(batch, batchSize);
}, 250));
} else {
reject(status);
}
} else {
routeElevations = routeElevations.concat(elevations);
resolve();
}
});
});
}
function addToChain(chain, batch, batchSize){
return chain.then(function(){
console.log('Promise add to chain for batch: ' + batch);
return getRouteElevationChartDataBatchPromise(batch, batchSize);
});
}
Примечание стороны;
Я также заказываю запрос DirectionService для обращения к 8-ми путевым ограничениям, которые имеет сервис, но я могу подтвердить, что это не проблема, так как я также столкнулся с проблемой с 8 или менее путевыми точками.
Problem;
Проблемы я сталкиваюсь являются:
- Данные о высоте не всегда после полного пути маршрута, а это означает последнюю точку возвышения на графике (далеко) от конца маршрута;
- Данные о высоте иногда отображаются в случайном порядке, как будто кажется, что обещания все еще не ожидали выполнения следующей задачи;
- Данные о высоте не всегда соответствуют данным
LatLng
отoverview_path
, предоставленных в данной партии (см. Снимок экрана); - Данные о расстоянии между перекрестными точками очень много. Иногда занимает несколько километров, в то же время запрашивая 512 образцов для равномерно совпадающего размера партии с максимальным количеством 200
LatLng
с за партию.
Я полагал дозирование в ElevationService с помощью Promises (и до того времени с setTimtout) будет решать все свои проблемы, но единственная проблема, я решил не превышая запрос URL 2,048 обугленных и перед описанной выше новой вопросы.
Помощь действительно оценили
Кроме того, я хотел бы поставить 250 респ. щедрость по этому вопросу прямо впереди, но это невозможно в данный момент. Поэтому, пожалуйста, не стесняйтесь отвечать, поскольку я могу позже добавить щедрость и наградить ее ответом, который решает описанные проблемы.
A 250 rep. награда была награждена, чтобы показать мою признательность за то, что вы указали мне в правильном направлении.
Спасибо за чтение и ответ!
Обновлен 4 апреля оставляя 1 отложенного вопроса (до тех пор, как я могу сказать на данный момент)
Проблема с возвышенностями в случайном порядке, решаемых вниз
Я был в состоянии решить некоторые о проблемах, когда я замечал непоследовательное поведение в результатах маршрутов. Это было вызвано по очевидной причине: асинхронные вызовы не были «обещаны», чтобы быть запланированными, поэтому некоторые из них были правильными, в большинстве случаев это не так. Я не заметил этого сначала, потому что маркеры были отображены правильно (кэшировано).
Проблема с подъемом между расстоянием решать вниз
В DIV отображающего данные высот были лишь 300px в ширину и содержащие много точек данных. По такой небольшой ширине я просто не мог нависнуть над достаточным количеством точек, заставляя запускать точки возвышения, которые лежат дальше друг от друга.
Проблема с данными высот не показывая по маршруту
Как-то куда-то вниз по линии Я также решил эту проблему, но я не уверен, если больше ширины или «Перспективный» порядок направления решил это.
До выпуска: данные о высоте не всегда полная
Единственный оставшийся вопрос заключается в том, что данные высота не всегда покрывает полный путь. Я считаю, что это связано с тем, что ошибка в логике Promising, потому что запись некоторых сообщений в консоли говорит мне, что диаграмма высот рисуется в точке, где не все Promise-then завершены, и я думаю, что это вызвано повторением пакетного вызова, когда Over Ошибка ограничения запроса возвращается API Карт Google.
Как я могу восстановить одну и ту же цепочку при возврате ошибки с превышением запроса? Я попытался не разрешить эту же функцию снова, но просто запустил setTimeout(...)
, но тогда Promise, похоже, не разрешает обновленную партию в настоящий момент, когда она больше не получает Over Over Query Limit. В настоящее время это, как я поставил его (в обоих направлениях и возвышения):
function getRouteElevationChartDataBatchPromise(batch, batchSize) {
return new Promise(function(resolve, reject) {
var elevator = new google.maps.ElevationService();
var thisBatchPath = [];
for (var j = batch * batchSize; j < batch * batchSize + batchSize; j++) {
if (j < directions.routes[0].overview_path.length) {
thisBatchPath.push(directions.routes[0].overview_path[j]);
} else {
break;
}
}
elevator.getElevationAlongPath({
path: thisBatchPath,
samples: 512
}, function (elevations, status) {
if (status != google.maps.ElevationStatus.OK) {
if(status == google.maps.ElevationStatus.OVER_QUERY_LIMIT) {
console.log('ElevationService: Over Query Limit, retrying in 200ms');
resolve(setTimeout(function() {
getRouteElevationChartDataBatchPromise(batch, batchSize);
}, 200));
} else {
reject(status);
}
} else {
console.log('Elevations Count: ' + elevations.length);
routeElevations = routeElevations.concat(elevations);
resolve();
}
});
});
}
Спасибо за ваш ответ. Но я не соглашаюсь (полностью) с вами. В рамках API Карт Google он обеспечивает отличные данные о высоте вдоль маршрута. Так; когда я выполняю эти запросы для выполнения вызова в заданных границах, ожидается ответ службы высотного обслуживания. Я только конкатенирую результаты, чтобы отображать несколько ответов в диаграмме. По-моему, это должно быть возможно. – Ben