Невозможно добавить маркеры Google внутри цикла - PullRequest
0 голосов
/ 15 марта 2020

Итак, я получаю адреса из своей базы данных пожарного магазина, преобразовываю их в координаты, затем пытаюсь добавить маркеры на основе каждого набора координат. Я могу добавить маркеры снаружи l oop, но не внутри.

Спасибо

    //Convert addresses to coords
    //Fetch all addresses from db
    db.collection('specials').get()
    .then(snapshot => {
        snapshot.forEach(special => {
            //Set location
            var location = special.data().address;

            //Get geocode info
            axios.get('https://maps.googleapis.com/maps/api/geocode/json?components=country:NZ|country:AU',{
                params:{
                    address:location, 
                    key:'************************************',  
                }
            })
            .then(function(response){
                //Geometry
                markerLat = response.data.results[0].geometry.location.lat;
                markerLng = response.data.results[0].geometry.location.lng; 

                //console.log("Lat:" + markerLat + " Lng:" + markerLng);

                //Doesn't work inside the loop
                markers.push({
                    coords:{lat: markerLat, lng: markerLng}
                });

            })
        });
    })

    //Works outside the loop
    markers.push({
        coords:{lat: -36.8585, lng: 174.7833}
    });

1 Ответ

3 голосов
/ 15 марта 2020

Мое первое предположение состоит в том, что вы используете markers вне l oop, например, при вызове API карт. Это не сработает, так как данные загружаются из Firestore асинхронно, и данные еще не доступны в этот момент.

Самый простой способ понять, как работает асинхронная загрузка, - это использовать некоторые хорошо расположенные операторы регистрации:

console.log("1. Before calling database");
db.collection('specials').get()
.then(snapshot => {
    console.log("2. Got database results, calling geocode API");
    snapshot.forEach(special => {
        var location = special.data().address;
        axios.get('https://maps.googleapis.com/maps/api/geocode/json?components=country:NZ|country:AU',{
            params:{ address:location,  key:'********' }
        })
        .then(function(response){
            console.log("3. Got geocode result");
        })
    });
})
console.log("4. After calling database");

Теперь, когда вы запустите этот код, вывод журнала будет:

  1. Перед вызовом базы данных

  2. После вызова базы данных

  3. Получил результаты базы данных, вызвав геокод API

  4. Получил результат геокода

  5. Получил результат геокодирования

...

Это, вероятно, не то, что вы ожидали, так как код не выполняется в том порядке, в котором вы имеете это в вашем файле. Но это полностью работает, как задумано, из-за природы асинхронных API. И это объясняет, почему местоположения из базы данных не добавляются в карты, если ваш вызов к картам находится рядом с оператором записи в лог 4.: к моменту запуска данные еще не были загружены из базы данных, и геокодирование не сохранилось. либо это еще не сделано.

Любой код, которому нужны данные из базы данных, должен находиться внутри обратного вызова then. Чтобы сделать все более сложным: поскольку вы также хотите, чтобы все геоаккумуляции были завершены, вы хотите добавлять маркеры на карты только после того, как все вложенные вызовы then() выполнены.

Для этого вы можете использовать Promise.all, который разрешает один then() после разрешения нескольких других вызовов then().

Объединение всего этого приводит к коду, который должен выглядеть примерно так:

//Fetch all addresses from db
db.collection('specials').get()
.then(snapshot => {
    // Get all addresses from the documents
    return snapshot.docs.map(doc => doc.data().address);
})
.then(addresses => {
    // Geocode all addresses, to get coordinates
    return Promise.all(addresses.map(location => {
        return axios.get('https://maps.googleapis.com/maps/api/geocode/json?components=country:NZ|country:AU',{
            params:{
                address:location, 
                key:'************************************',  
            }
        })
    });
})
.then(locations => {
    // Convert all geometry into markers
    return locations.map(response => {
        markerLat = response.data.results[0].geometry.location.lat;
        markerLng = response.data.results[0].geometry.location.lng; 

        return  {
            coords:{lat: markerLat, lng: markerLng}
        });
    });
})
.then(markers => {
    // TODO: call the maps API and add the markers
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...