Неточный ответ Google Maps Elevation Service при разбиении слишком большого пути

Это небольшой вопрос с некоторым уровнем детализации, поэтому позвольте мне сначала объяснить ситуацию, затем мою реализацию и, наконец, вопрос, чтобы вы лучше поняли.

По состоянию на 4 апреля добавлено обновление, и проблемы сужены до одной нерешенной проблемы, см. Нижнюю часть этого вопроса для получения актуальной информации.

TLDR;

Я получил длинный маршрут, возвращенный из API Google Maps Directions, и хочу получить карту высот для этого маршрута. Жаль, что он не работает, потому что он запрашивается через GET, а максимальная длина URL составляет 2,048 символов, которые превышаются. Я разделил запросы; гарантирует правильную обработку заказа с помощью Promises; но данные Evelation не всегда полны для полного маршрута, не всегда отображаются в правильном порядке, не всегда следуют заданному пути, а расположение мест возвышения иногда превышает несколько километров.

Вступление;

Пытаясь создать диаграмму высот для ответа Google Maps DirectionsService, я столкнулся с проблемой слишком длинных маршрутов (кажется, что это не связано с расстоянием, а не с количеством LatLngs на Overview_path). Это вызвано тем, что ElevationService запрашивается черезGET и максимальная длина URL составляет 2048 символов. Эта проблемаописано на SO здесь, а также.

Реализация;

Я подумал, что буду умнее, чем Google (не совсем, но, по крайней мере, пытаюсь найти способ обойти это), чтобы разделить путь, возвращаемый DirectionsService (overview_path собственности) на партии и объединить результаты (elevations возвращается методом ElevationServicegetElevationsAlongPath).

Чтобы получить наилучший уровень детализации, я запрашиваю сервис 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 или меньшим количеством путевых точек.

Проблема;

Проблемы, с которыми я сталкиваюсь:

Данные высотных отметок не всегда соответствуют полному пути маршрута, а это означает, что последняя точка высот на карте (далеко) от конца маршрута;Данные о высоте иногда отображаются в случайном порядке, как будто кажется, что обещания все еще не ожидали выполнения следующей задачи;Данные о высотах не всегда соответствуют заданнымLatLngизoverview_path предоставляется в данной партии (см. скриншот);Данные о расстоянии между отметками очень много. Иногда охватывает несколько километров при запросе 512 образцов для равномерно подобранного размера партии с максимальным количеством 200LatLngс за партию.

Я полагал, что пакетирование ElevationService с помощью Promises (и до синхронизации с setTimtout) решит все мои проблемы, но единственная проблема, которую я решил, - не превышать URL-адрес запроса 2.048 и сталкиваться с вышеописанными новыми проблемами.

Помощь очень ценится

Также я хотел бы поставить 250 респ. щедрость на этот вопрос прямо сейчас, но это невозможно в данный момент. Поэтому, пожалуйста, не стесняйтесь отвечать, так как позже я смогу добавить награду и наградить ее ответом, который решает описанные проблемы. 250 респ. Награда была вручена, чтобы показать мою признательность за то, что вы указали мне правильное направление.

Спасибо за чтение и ответ!

Обновлено 4 апреля, оставив 1 незавершенный вопрос (насколько я могу судить на данный момент)

Проблема с возвышениями в случайном порядке решена

Мне удалось решить некоторые проблемы, когда я заметил непоследовательное поведение в результатах. Это было вызвано очевидной причиной: асинхронные вызовы не были «обещаны», чтобы быть запланированными, поэтому в некоторых случаях порядок был правильным, в большинстве случаев это было не так. Сначала я этого не заметил, потому что маркеры отображались правильно (кэшировались).

Проблема с расстоянием между высотами решена

Div, отображающий данные высот, имел ширину всего 300 пикселей и содержал много точек данных. Из-за такой малой ширины я просто не мог парить над достаточным количеством точек, что приводило к появлению точек возвышения, которые находятся дальше друг от друга.

Проблема с данными о высоте, не отображаемыми по маршруту

Каким-то образом где-то внизу я также решил эту проблему, но я не уверен, что большая ширина или «многообещающий» порядок направлений решил эту проблему.

Нерешенная проблема: данные высот не всегда полны

Единственная оставшаяся проблема заключается в том, что данные высот не всегда охватывают полный путь. Я полагаю, что это связано с ошибкой в ​​логике Promising, поскольку регистрация некоторых сообщений в консоли говорит мне, что диаграмма высот рисуется в точке, где не все Promise-then завершены, и я думаю, что это вызвано повторным вызовом пакетного вызова, когда Over Ошибка лимита запросов возвращается API Карт Google.

Как я могу перефразировать ту же цепочку, когда возвращается ошибка Over Query Limit? Я пытался не разрешать ту же функцию снова, а просто запуститьsetTimeout(...), но в этом случае Promise, похоже, не разрешает обновленный пакет в тот момент, когда он больше не получает лимит 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();
            }
        });
    });
}

Ответы на вопрос(3)

Ваш ответ на вопрос