【问题标题】:Unable to receive proper data from the promise function无法从 Promise 函数接收正确的数据
【发布时间】:2017-07-26 15:33:25
【问题描述】:

我正在尝试通过首先废弃第一页然后转到航空公司的每个单独页面以获取网站 url 来废弃 wikipedia 页面以获取航空公司列表。我将代码分为两个功能。一个是废弃主页并获取一个新的 url,第二个函数是从创建的 url 废弃另一个页面以从该页面获取网站名称。我已经使用 request-promise 模块来获取 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;

    })

但是,当我在父函数中控制台记录 answer 变量时,我得到一个 [object Promise] 值而不是字符串。我该如何解决这个问题?

【问题讨论】:

  • airline_url 返回对象承诺?
  • 是的,当我控制台记录它时,它会给出 [object Promise]。
  • 我的猜测是您正在尝试在代码中的其他位置使用请求设置span.url 的内容,但是请求是异步的,并且这个请求返回了一个承诺,所以无论您身在何处设置span.url 的文本,在成功的promise 回调中进行,不要将它设置为promise 的值。 MDN Promise,通过设置看起来像$(..).text(someReq()); function someReq() { ... return promise; }的承诺来扩展我的意思@
  • @PatrickBarr span.url 只是一个包含 url 的文本,该文本被传递给另一个函数以解析该页面。

标签: javascript node.js ecmascript-6 cheerio request-promise


【解决方案1】:

异步函数返回promise。在这种情况下,你需要使用then来获得resolved response或使用await。 如果您的代码的其他部分没问题,这应该可以工作。

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}`);
   }
 });
}

【讨论】:

  • 对于无法分辨的人来说,发现的区别是在$("tr").each(...)await 前面的getAirlineUrl(wiki_url); 前面的箭头函数中添加了async
  • 它现在返回未处理的承诺拒绝错误
  • 在异步函数中使用 try..catch 来捕获错误。
  • 使用这种方法,getAirlinesWebsites 将在 getAirlineUrl 函数完成之前评估并解决其承诺。
【解决方案2】:

由于您的getAirlineUrl 函数返回一个promise,您需要await 该promise。您不能将 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}`);
    }
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-27
    • 2021-04-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多