【问题标题】:small issue with async await on nodejsnodejs上异步等待的小问题
【发布时间】:2020-06-11 01:24:42
【问题描述】:

我知道问题出在异步等待中。基本上在下面的代码中,第 80 行在第 76 行之前运行,因此返回空值。我该如何纠正这个问题?

我基本上是在使用cheerio 构建一个刮板,当从刮板加载数据需要时间时,就会出现问题。

https://github.com/galdiatorocks/scraper/blob/master/server.js

const request = require('request');
const cheerio = require('cheerio');
const mongoose = require("mongoose");

mongoose.connect(process.env.DB, {
    useNewUrlParser: true,
    useFindAndModify: false,
    useCreateIndex: true,
    useUnifiedTopology: true
  });
  mongoose.Promise = global.Promise;
  let db = mongoose.connection;
  db.on("error", console.error.bind(console, "MongoDB connection error:"));


scrapeItems();

function scrapeItems(){

    const LeaderModel = require("./leader_model");

    LeaderModel.find({}, (err,doc) => {
        if(err) {console.error(err)};

        doc.forEach(async (data) => {

            data.booksReco = await readPage(data.storyLink, (error, dat) => {
                if(err)  console.error(error);
                console.log(dat);
            });
            //console.log(data.booksReco);
        })
    })


}

function readPage(URL){
    request(URL, async function(err, response, body){

        if (err) console.error(err);

        //console.log(err, response, body);
        let $ = cheerio.load(body);
        let booksReco = [];


        await $('#page tr').each(async (roll, data) => {

            let bookdetail = {};
            const bookImgPath = await $(data)  .find('.kniga')
                                                    .children('a')
                                                    .children('img')
                                                    .attr('src');
            if(bookImgPath){
                bookdetail.bookImgPath = bookImgPath;

                const detail = $(data).find('.opisanie')

                bookdetail.bookName = detail.children('a').text().split(/\sby\s/);
                bookdetail.bookAuthor = bookdetail.bookName[1];
                bookdetail.bookName = bookdetail.bookName[0];
                bookdetail.amazonLink = detail.children('a').attr('href');
                bookdetail.leaderComment = detail.children('.quote2').text();

                if(!bookdetail.leaderComment){
                    bookdetail.leaderCommentImg = detail.children('.quote2').children('img').attr('src');
                    bookdetail.whereRecommended = detail.children('.pho').text();
                } else {
                    bookdetail.whereRecommended = detail.children('.recom').text();
                }

                bookdetail.bookDesc = detail.children('.description').text();

                console.log(bookdetail.bookName, bookdetail.bookAuthor);
                booksReco.push(bookdetail);
                console.log(booksReco);
            }
        });
        console.log(booksReco);
        return(booksReco);

    })
}

【问题讨论】:

    标签: node.js asynchronous async-await cheerio


    【解决方案1】:

    Cheerio 的.each() 同步运行,无需使用async/await。你可以这样做:

    $('#page tr').each((roll, data) => {
    
        let bookdetail = {};
        const bookImgPath = $(data).find('.kniga')
            .children('a')
            .children('img')
            .attr('src');
    ...
    });
    

    同时执行request(URL, async function(err, response, body){ 也不起作用,因为这里没有返回任何可以等待的承诺。您可以通过将请求包装在承诺中来解决此问题:

    function readPage(URL){
        return new Promise((resolve,reject) => {
            request(URL, (err, response, body) => {
                if(err) reject(err);
                // do your cheerio logic here and resolve the result
                resolve(booksReco);
            });
    });
    

    【讨论】:

      【解决方案2】:

      您应该使用map 而不是each

      let booksReco = $('#page tr').map((roll, data) => {
        let bookdetail = {};
        // more stuff
        return bookdetail
      }).get()
      console.log(booksReco);
      

      【讨论】:

      • 这并没有解决异步操作的问题。 :| console.log 在地图完成之前运行。
      【解决方案3】:

      所以我在调用函数 readPage 时必须使用 async/await/promise。

      最后用这个来解决问题

      
          if (roll == elements.length - 1) {
                       resolve(booksReco);
                      }
      
      

      感谢大家的帮助:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-11
        • 1970-01-01
        • 2018-12-09
        相关资源
        最近更新 更多