Когда я запускаю node index.js
с этим кодом, все работает правильно. Что он делает, так это получает случайную координату с помощью функции randomGeo, а затем преобразует ее в адрес с помощью вызова Axios. Наконец, эта функция transPredtoJSON вызывается в .then вызова Axios, который берет адрес и добавляет его в файл JSON. Проблема возникает, когда я хочу выполнить это более одного раза, что я покажу в следующем фрагменте кода.
randomCoordinate = randomGeo({ latitude: originlat, longitude: originlng }, radius)
lat = randomCoordinate.latitude
lng = randomCoordinate.longitude
reverseGeoCodeURL = `https://maps.googleapis.com/maps/api/geocode/json?latlng=${lat},${lng}&key=${GEOCODE_API_KEY}`
// get closest address to the coordinate
axios.get(reverseGeoCodeURL).then(res => {
let ranAddr = res.data.results[0].formatted_address
let correctCity = /, Southlake,/i
if (correctCity.exec(ranAddr)) { // only Southlake addresses
transPredtoJSON(ranAddr) // are added to the output json file
}
}).catch(error => {
console.error('error: ', error);
})
Ниже я заключаю приведенный выше код в цикл while. У меня будет счетчик, который будет отслеживать, сколько адресов было добавлено в выходной файл, и останавливаться, когда он достигает своего предела. Кроме того, axios.get никогда не вызывается, потому что журнал консоли выводит только count: 0
бесконечно. Странно то, что когда я перемещаю count += 1
сразу после вызова axios, чтобы счетчик увеличивался независимо от того, добавлен адрес или нет, вызывается axios.get и добавляет адреса в файл, как и предполагалось. Почему Axios не работает в этом цикле?
let enoughAddresses = 10
let count = 0
while (count < enoughAddresses) {
console.info('count', count);
randomCoordinate = randomGeo({ latitude: originlat, longitude: originlng }, radius)
lat = randomCoordinate.latitude
lng = randomCoordinate.longitude
reverseGeoCodeURL = `https://maps.googleapis.com/maps/api/geocode/json?latlng=${lat},${lng}&key=${key}`
axios.get(reverseGeoCodeURL).then(res => {
console.info('inside axios .then');
let ranAddr = res.data.results[0].formatted_address
let corrCity = /, Southlake,/i
if (corrCity.exec(ranAddr)) {
transPredtoJSON(ranAddr)
count += 1 // only increment count when an address has been added
console.info('count', count);
}
}).catch(error => {
console.error('error: ', error);
})
}
Проблема в том, что функция axios работает асинхронно. Вероятно, вы можете использовать обещание, чтобы решить эту проблему.
этот псевдокод может указать вам правильное направление:
let enoughAddresses = 10
for (i = 0; i < enoughAddresses; i++) {
addresses.push(new Promise((r, j) => {
// your async function to get addresses
});
}
// returns a promise when all your async functions are done
Promise.all(addresses).then((values) => {
// values should contain your addresses
});
также это для справки.
Спасибо за ответ! Я не думал, что у меня возникнет проблема с асинхронностью, потому что вся логика находится в .then, который работает синхронно; но на самом деле происходит то, что цикл while будет повторяться сотни раз, прежде чем будет вызван axios.get. Для решения я завернул цикл while в асинхронный IIFE и ждал вызова axios.