Как изменить Google отрегулировал вызовы на выполненные обещания - PullRequest
0 голосов
/ 06 февраля 2019

Я пытаюсь добавить широту и длину данных для адресации записей в нашей базе данных, чтобы мы могли предоставить локатор магазина, например страницуЯ использовал эту страницу в качестве руководства.Я пытаюсь создать CSV-файл геокодированных адресов с идентификаторами для импорта в нашу базу данных.В конце концов я хочу автоматизировать это, но сейчас я делаю это вручную для начальной загрузки.

У нас есть более 3000 записей в нашей базе данных, и я продолжаю выходить за пределы запросов с помощью API геокодирования.Я добавил задержку для каждого запроса, как предложено для нескольких вопросов здесь.К сожалению, большинство из этих ответов до того, как Google изменил структуру цен и квоту на свои API.Кажется, что после 1000 или около того я продолжаю получать страшную ошибку API OVER QUERY LIMIT.Некоторые вызовы работают после того, как я получаю сообщение об ошибке, но чем дольше я выполняю код, тем меньше отношение успеха к ошибкам.

В документации Google говорится, что QPS для геокодирования составляет 50, но я обнаружил проблемы при выполнении более 10.Поэтому я добавил задержку в 1500 мс для разметки своих запросов, но она, похоже, не работает.Оплата премиального плана не вариант, так как нам нужно делать это каждые 30 дней, согласно политике хранения данных Google.Я делаю это на стороне клиента, так как на нашем сервере нет настроек java, node, pip или go.

Редактировать: я провел еще несколько поисков и включил геокодирование в функцию, и если онане удается, рекурсивно вызвать его снова после задержки.Но страница продолжает падать, как только я получаю, я начинаю получать ошибки сверх лимита.Чего я не понимаю, так это того, почему он выдает сотни таких ошибок, больше, чем количество адресов для анализа, если я возвращаю ошибочные вызовы в функции setTimeout.

Edit2: Ok IПодхожу ближе.Я заставил свою функцию геокодирования вернуть обещание и объявил его вне основного кода.Обтекание setTimeout над разделом, в котором goecodes распределили их соответствующим образом.Я установил перехват для устранения ошибки и повторите попытку.Теперь моя проблема в том, что мой Promise.all() разрешается, даже если некоторые из обещаний не выполнены и все еще находятся в процессе повторной попытки.Я не хочу, чтобы он выполнялся до тех пор, пока не будут решены невыполненные обещания.

Мой код выглядит следующим образом:

db.php

<?php

$mysqli = new mysqli("host", "user", "pass", "table");
$addresses = array();

if ($mysqli->connect_errno) {
    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
$query = "SELECT
    id,
    Concat(
        primary_address_street, ' ', primary_address_city,
        ' ', primary_address_state, ' ',
        primary_address_postalcode
    ) as address
FROM
    `nurses`
WHERE
    primary_address_postalcode <> ''
    AND primary_address_street <> ''
    AND primary_address_city <> ''
    AND primary_address_state <> ''
    AND first_name <> ''
    AND last_name <> ''
    ";

$i = 0;
//Used multi_query because I originally did multiple queries
if ($mysqli->multi_query($query)) {
    do {
        if ($result = $mysqli->store_result()) {
            while ($row = $result->fetch_row()) {
                $addresses[$i] = array('id' => $row[0], 'address' => $row[1]);
                $i++;
            }
            $result->free();
        }
    } while ($mysqli->next_result());
}

echo json_encode($addresses);

map.js

var map;
var nurses = [];

function initMap() {
    map = new google.maps.Map(document.getElementById('map'), {
        center: { lat: myLat, lng: myLng },
        zoom: 15,
        // disableDefaultUI: true,
        // gestureHandling: 'none',
        // zoomControl: false
    });

    var bounds = new google.maps.LatLngBounds();
    var geocoder = new google.maps.Geocoder();

    var oReq = new XMLHttpRequest();
    oReq.onload = function() {
        // console.log(this.responseText);
        var dbAdresses = JSON.parse(this.responseText);
        // console.log(dbAdresses);

        var locationPromises = [];
        dbAdresses.forEach(function(e, i) {
            locationPromises.push(geocodeAddress(e, i));
        });

        Promise.all(locationPromises)
            .then(function(locationsFound) {
                // console.log(locationsFound);
                // console.log(nurses);
                const replacer = (key, value) => value === null ? '' : value;
                const header = Object.keys(nurses[0]);
                let csv = nurses.map(row => header.map(fieldName => JSON.stringify(row[fieldName], replacer)).join(','));
                csv.unshift(header.join(','));
                csv = csv.join('\r\n');

                //Download the file as CSV
                var downloadLink = document.createElement("a");
                var blob = new Blob(["\ufeff", csv]);
                var url = URL.createObjectURL(blob);
                downloadLink.href = url;
                downloadLink.download = "nurses-addresses.csv";
                document.body.appendChild(downloadLink);
                downloadLink.click();
                document.body.removeChild(downloadLink);
            })
            .catch(function(e) { console.log(e); });
    };
    oReq.open("get", "db_csv.php", true);
    oReq.send();
}

function geocodeAddress(entry, index) {
    var geocoder = new google.maps.Geocoder();
    return new Promise(function(resolve, reject) {
            setTimeout(function() {
                geocoder.geocode({
                    'address': JSON.stringify(entry.address)
                }, function(results, status) {
                    if (status == google.maps.GeocoderStatus.OK) {
                        console.log(results);
                        var person = {
                            'id': entry.id,
                            'lat': results[0].geometry.location.lat(),
                            'lng': results[0].geometry.location.lng()
                        };
                        nurses.push(person);
                        resolve(results);
                    } else {
                        console.log("Geocode was not successful for the following reason: " + status);
                        reject(status);
                    }
                });
            }, 1000 * index);
        })
        .catch(function() {
            console.log(entry.id + " failed retrying in 5 seconds");
            setTimeout(function() {
                geocodeAddress(entry, index);
            }, 5000);
        });
}
...