Я работаю над простым погодным приложением, которое использует базу данных mysql, в которой есть только названия городов. Затем я запрашиваю базу данных для всех имен и отправляю запрос в API openweathermap для получения информации о погоде.
function getCities() {
con.connect();
con.query(('SELECT city_name FROM cities'), (err, res) => {
console.info(res);
getWeather(cities);
});
};
async function getWeather(cities) {
var data = [];
for (var i = 0; i < cities.length; i++) {
var url = `http://api.openweathermap.org/data/2.5/weather?q=${cities[i].city_name}&units=metric&appid=271d1234d3f497eed5b1d80a07b3fcd1`;
await request(url, (err, res, body) => {
var json = JSON.parse(body);
var weather = {
city: json.name,
temperature: json.main.temp,
description: json.weather[0].description,
icon: json.weather[0].icon
};
data.push(weather);
});
}
console.info(data);
}
Функция getCities() работает так, как ожидалось, и возвращает все города, но ошибки возникают в функции getWeather, в частности, эти ошибки:
Desktop/WeatherApp/node_modules/request-promise-core/lib/plumbing.js:130
throw thrownException;
^
TypeError: Cannot read property 'temp' of undefined
at Request.request [as _rp_callbackOrig] (/home/kristijan/Desktop/WeatherApp/app.js:60:41)
at Request.plumbing.callback (/home/kristijan/Desktop/WeatherApp/node_modules/request-promise-core/lib/plumbing.js:76:39)
at Request.RP$callback [as _callback] (/home/kristijan/Desktop/WeatherApp/node_modules/request-promise-core/lib/plumbing.js:46:31)
at Request.self.callback (/home/kristijan/Desktop/WeatherApp/node_modules/request/request.js:185:22)
at Request.emit (events.js:182:13)
at Request.<anonymous> (/home/kristijan/Desktop/WeatherApp/node_modules/request/request.js:1161:10)
at Request.emit (events.js:182:13)
at IncomingMessage.<anonymous> (/home/kristijan/Desktop/WeatherApp/node_modules/request/request.js:1083:12)
at Object.onceWrapper (events.js:273:13)
at IncomingMessage.emit (events.js:187:15)
at endReadableNT (_stream_readable.js:1094:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
Насколько я понял, это перескакивает внутрь функции стрелки, прежде чем получить результат от API?
Исправлена его часть, теперь он фактически возвращает данные. Единственное, о чем я сейчас не могу сказать, - это когда я визуализирую страницу, как мне сначала дождаться возврата данных, а затем визуализировать их.
Пожалуйста, сделайте отступ в коде должным образом (вы можете исправить это с помощью ссылки "изменить"). Очень сложно читать код с ложным отступом.
Возможно, вы не захотите подключаться каждый раз, когда кто-то вызывает getCities(), потому что, если это действительно создает соединение с вашим экземпляром MySQL, это очень дорогой вызов, который иногда может завершаться неудачно - было бы лучше сохранить соединение как одноэлементное или просто член переменная в локальном контексте



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


await ожидает асинхронной операции только в том случае, если ожидаемый результат функции возвращает обещание. Функция request() не возвращает обещание (она работает с обратным вызовом, который вы ей передаете), и поэтому await не ждет этого результата. Вместо этого вы можете использовать библиотеку request-promise, которая возвращает обещание, а вы не передаете ему обратный вызов.
Вот пример:
const rp = require('request-promise');
async function getWeather(cities) {
let data = [];
for (let i = 0; i < cities.length; i++) {
let url = `http://api.openweathermap.org/data/2.5/weather?q=${cities[i].city_name}&units=metric&appid=271d1234d3f497eed5b1d80a07b3fcd1`;
let body = await rp(url);
let json = JSON.parse(body);
let weather = {
city: json.name,
temperature: json.main.temp,
description: json.weather[0].description,
icon: json.weather[0].icon
};
data.push(weather);
}
console.info(data);
}
Обратите внимание, что вы также можете позволить API запроса автоматически анализировать JSON:
const rp = require('request-promise');
async function getWeather(cities) {
let data = [];
for (let i = 0; i < cities.length; i++) {
let url = `http://api.openweathermap.org/data/2.5/weather?q=${cities[i].city_name}&units=metric&appid=271d1234d3f497eed5b1d80a07b3fcd1`;
let json = await rp({uri:url, json: true});
let weather = {
city: json.name,
temperature: json.main.temp,
description: json.weather[0].description,
icon: json.weather[0].icon
};
data.push(weather);
}
console.info(data);
}
РЕДАКТИРОВАТЬ Январь, 2020 - модуль request () в режиме обслуживания
К вашему сведению, модуль request и его производные, такие как request-promise, сейчас находятся в режиме обслуживания и не будут активно разрабатываться для добавления новых функций. Подробнее о рассуждениях здесь можно прочитать. В этот стол есть список альтернатив с некоторым обсуждением каждой из них. Я сам использую got(), он с самого начала построен с использованием обещаний и прост в использовании.
requestне возвращает обещание, поэтому вашawaitничего не делает. Вам действительно нужно использовать обещания.