NodeJS нет данных, возвращаемых функцией

Я работаю над простым погодным приложением, которое использует базу данных 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?

request не возвращает обещание, поэтому ваш await ничего не делает. Вам действительно нужно использовать обещания.
SLaks 01.01.2019 19:41

Исправлена ​​его часть, теперь он фактически возвращает данные. Единственное, о чем я сейчас не могу сказать, - это когда я визуализирую страницу, как мне сначала дождаться возврата данных, а затем визуализировать их.

Kristijan Stefanoski 01.01.2019 19:43

Пожалуйста, сделайте отступ в коде должным образом (вы можете исправить это с помощью ссылки "изменить"). Очень сложно читать код с ложным отступом.

jfriend00 01.01.2019 19:44

Возможно, вы не захотите подключаться каждый раз, когда кто-то вызывает getCities(), потому что, если это действительно создает соединение с вашим экземпляром MySQL, это очень дорогой вызов, который иногда может завершаться неудачно - было бы лучше сохранить соединение как одноэлементное или просто член переменная в локальном контексте

johnheroy 01.01.2019 19:49
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
4
186
1

Ответы 1

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(), он с самого начала построен с использованием обещаний и прост в использовании.

Другие вопросы по теме