繁体   English   中英

使用 Promise 时将变量传递给外部 scope 的最佳实践是什么?

[英]What are the best practices to pass variable to outer scope while using Promise?

我正在使用 Cheerio 和 puppeteer 编写 Scraper 脚本。 在每个循环中,我想解析一个重定向的 url 字段。 使用 Promise 我可以控制台记录它,但将它插入元数据的最佳方法是什么?

我实际上也对控制流感到困惑。

(async function main() {

    const browser = await puppeteer.launch({
        headless: true,
    });

    const page = await browser.newPage();

    await page.goto('https://www.example.com/?q=async+urls&s=s');

    const content = await page.content();

    const $ = cheerio.load(content);

    var parsedResults = [];

    const fetchRedirect = async (url) => {
        try {
            let response = await doRequest(url);
          return response;
        } catch (err) {
          return false;
        }
      };

    const videoBlocks = $('td[itemprop="subjectOf"]').first().each(function (i, element) {


    const url = ($(this).find('a.title').attr('href'));

    const fetchUrl = fetchRedirect(url);
   
    // ** i can console log the redirected url **/
    fetchUrl.then(url => console.log(url));

        const title = ($(this).find('a.title').text());

        var metadata = {
            title
        };

        parsedResults.push(metadata);

    });

    function doRequest(url) {
        return new Promise(function (resolve, reject) {
          request(url, function (error, res, body) {
            if (!error) {
              resolve(getPathFromUrl(res.request.uri.href));
            } else {
              reject(error);
            }
          });
        });
      }

    function getPathFromUrl(url) {
        return url.split(/[?#]/)[0];
    
    }   
    console.log(parsedResults);
    await page.close()
    await browser.close();
})();
//...............await!
const fetchUrl = await fetchRedirect(url);

// ** then instead that **/
// fetchUrl.then(url => console.log(url));
// just
console.log(fetchUrl)
const title = ($(this).find('a.title').text());

var metadata = {
    title
};

parsedResults.push(metadata);

就我个人而言,我会 go 用于节点模块。 像这样的代码很难阅读,因为您在一个函数(main)中声明了多个函数。 是否应用 OOP 或函数式编程取决于您的偏好(第二种在 Node 环境中更受欢迎,但如果我要围绕特定实体创建功能,我更喜欢第一种)。 避免嵌套和抽象函数(您在其他函数中声明的函数)对于创建可重用和可读的代码至关重要。

这是一个工作原型(未经测试)。 它使 puppeteer 实例可重用。 该模块公开了三个方法:start、stop、 crawlWeb

'use strict'

var browser;

async function crawlWeb(options) {
    // validate options and throw errors
    if (!options.url) {
        throw new Error('url is invalid');
    }

    if (!browser) {
        throw new Error('puppeteer is not started');
    }

    const page = await browser.newPage();

    await page.goto(optionsl.url);

    const content = await page.content();

    const $ = cheerio.load(content);

    const metas = extracMetadata($);

    for (let metadata of metas) {
        // you can verify if site is valid
        // you can use await
        try {
            await doRequest(metadata.url);
        }
        catch(err) {
            // do something if not valid
        }
    }

    return metas;
}

async function start(options) {
    browser = await puppeteer.launch(options);
}

async function stop() {
    if (!browser) {
        throw new Error('puppeteer is not started');
    }

    await page.close()
    await browser.close();

}

function extracMetadata($) {
    const metas = [];
    $('td[itemprop="subjectOf"]').first().each(function (i, element) {
        const url = ($(this).find('a.title').attr('href'));

        const title = ($(this).find('a.title').text());

        var metadata = {
            url,
            title
        };
        metas.push(metadata);
    });

    return metas;
}

function doRequest(url) {
    return new Promise(function (resolve, reject) {
        request(url, function (error, res, body) {
            if (!error) {
                resolve(getPathFromUrl(res.request.uri.href));
            } else {
                reject(error);
            }
        });
    });
}

function getPathFromUrl(url) {
    return url.split(/[?#]/)[0];
}

module.exports = {
    crawlWeb,
    start,
    stop
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM