Не удалось получить правильные данные из функции обещания

Я пытаюсь удалить страницу википедии, чтобы получить список авиакомпаний, сначала удалив первую страницу, а затем перейдя на каждую отдельную страницу авиакомпании, чтобы получить URL-адрес веб-сайта. Я разделил код на две функции. Одна для удаления главной страницы и получения нового URL-адреса, а вторая функция для удаления другой страницы из созданного URL-адреса, чтобы получить имя веб-сайта с этой страницы. Я использовал модуль запроса-обещания для получения html, а затем cheerio для анализа данных.

export async function getAirlinesWebsites(req,res) {

let response = await request(options_mainpage);
console.log(`Data`);

let $ = cheerio.load(response);
console.log('Response got');

 $('tr').each((i,e)=>{
     let children = '';
    console.log('inside function ', i);
        if($(e).children('td').children('a').attr('class') !== 'new') {
            children = $(e).children('td').children('a').attr('href');


            let wiki_url = 'https://en.wikipedia.org' + children;
            console.log(`wiki_url = ${wiki_url}`);

             let airline_url = getAirlineUrl(wiki_url);
             console.log(`airline_url = ${airline_url}`);
        }
})

И затем функция getAirlineUrl() будет анализировать другую страницу на основе предоставленного URL-адреса.

async function getAirlineUrl(url){

    const wiki_child_options = {
        url : url,
        headers : headers
    }


   let child_response = await request(wiki_child_options);
        let $ = cheerio.load(child_response);

        let answer = $('.infobox.vcard').children('tbody').children('tr').children('td').children('span.url').text();

        return answer;

    })

Однако, когда я консольно регистрирую переменную ответа в родительской функции, я получаю значение [object Promise] вместо строки. Как решить эту проблему?


person Ahsan Jamal    schedule 26.07.2017    source источник
comment
авиакомпания_url возвращает обещание объекта?   -  person error404    schedule 26.07.2017
comment
да, он дает [object Promise], когда я записываю его в консоль.   -  person Ahsan Jamal    schedule 26.07.2017
comment
Я предполагаю, что вы пытаетесь установить содержимое span.url с запросом где-то еще в коде, но запросы асинхронны, и этот возвращает обещание, поэтому, где бы вы ни устанавливали текст span.url, делайте это в успешном обратном вызове обещания , не устанавливайте его в значение обещания. Обещание MDN, расширяя то, что я имею в виду установив обещание, это выглядит как $(..).text(someReq()); function someReq() { ... return promise; }   -  person Patrick Barr    schedule 26.07.2017
comment
@PatrickBarr span.url — это просто текст, содержащий URL-адрес, который передается другой функции для анализа этой страницы.   -  person Ahsan Jamal    schedule 26.07.2017


Ответы (2)


Асинхронная функция возвращает обещание. В этом случае вам нужно использовать then, чтобы получить разрешенный ответ или использовать ожидание. Это должно работать, если другая часть вашего кода в порядке.

export async function getAirlinesWebsites(req, res) {
  let response = await request(options_mainpage);
  console.log(`Data`);

  let $ = cheerio.load(response);
  console.log("Response got");

  $("tr").each(async (i, e) => {
   let children = "";
   console.log("inside function ", i);
   if ($(e).children("td").children("a").attr("class") !== "new") {
     children = $(e).children("td").children("a").attr("href");

     let wiki_url = "https://en.wikipedia.org" + children;
     console.log(`wiki_url = ${wiki_url}`);

     let airline_url = await getAirlineUrl(wiki_url);
     console.log(`airline_url = ${airline_url}`);
   }
 });
}
person error404    schedule 26.07.2017
comment
Для тех, кто не может сказать, замеченные различия заключаются в добавлении async к стрелочной функции внутри $("tr").each(...) и await перед getAirlineUrl(wiki_url);. - person Patrick Roberts; 26.07.2017
comment
Теперь он возвращает ошибку отклонения необработанного обещания - person Ahsan Jamal; 26.07.2017
comment
Используйте try..catch внутри асинхронной функции, чтобы поймать ошибку. - person error404; 26.07.2017
comment
При таком подходе getAirlinesWebsites оценит и разрешит свое обещание до завершения функций getAirlineUrl. - person loganfsmyth; 26.07.2017

Поскольку ваша функция getAirlineUrl возвращает обещание, вам нужно await выполнить это обещание. Вы не можете вложить await внутри обратного вызова .each, потому что обратный вызов не является асинхронной функцией, и если бы это было так, он бы все равно не работал. Лучшее решение — избегать использования .each и просто использовать цикл.

export async function getAirlinesWebsites(req,res) {

  let response = await request(options_mainpage);
  console.log(`Data`);

  let $ = cheerio.load(response);
  console.log('Response got');

  for (const [i, e] of Array.from($('tr')).entries()) {
    let children = '';
    console.log('inside function ', i);
    if($(e).children('td').children('a').attr('class') !== 'new') {
      children = $(e).children('td').children('a').attr('href');


      let wiki_url = 'https://en.wikipedia.org' + children;
      console.log(`wiki_url = ${wiki_url}`);

      let airline_url = await getAirlineUrl(wiki_url);
      console.log(`airline_url = ${airline_url}`);
    }
  }
}
person loganfsmyth    schedule 26.07.2017