【问题标题】:NodeJs module.exports, one function calls other. Other is not definedNodeJs module.exports,一个函数调用另一个。其他未定义
【发布时间】:2021-08-16 19:14:00
【问题描述】:

我尝试了很多之前已在此处发布的建议修复,但我真的不知道我还能做什么。

在刮刀中,我有 3 个功能。一个主,两个帮手。我在路由中导入 index.js。

const { scrape, scrapeChannel, iterateProducts } = require('../../services/scrapers.js');

然后我调用了 scrapeChannel('url') 但我一直在获取未定义的 scrape。当我 console.log(scrape) 显示它存在于 index.js 中

scrapers.js 所有函数都是这样导出的

module.exports.iterateProducts = function()  {logic}

这是整个导入的样子

@马克 index.js

   const express = require('express');
const router = express.Router();

const { scrape, scrapeChannel, iterateProducts } = require('../../services/scrapers.js');

let content = scrapeChannel('Placeholder cuz private, its working');
console.log(content)
router.get('/', async (req,res) => {   
    const creators = [
        {name: "Test test", img: 'https://'},
        {name: "bRAH BDSF", img: 'https://'},
        {name: "123 123", img: 'https://'},
    ]

    res.render('site/show')
})

router.post('/', async (req,res) => {
    console.log(req.body)
    res.send('succes')
})


module.exports = router;

scrapers.js

const puppeteer = require('puppeteer');


module.exports.scrape = function () {
    let list = Array.from(document.querySelectorAll(".selenium-price-normal"), e => e.innerText);
    let name = Array.from(document.querySelectorAll(" div.product-header > h2 > a"), e => e.innerText);
    return [list, name];
}

module.exports.iterateProducts = function (productName, productPrice){
    let titles = [];
    let prices = [];
    for (let i = 0; i < productName.length - 4; i++) {
        titles.push(productName[i]);
    }
    for (let y = 1; y < productPrice.length - 3; y = y + 2) {
        prices.push(productPrice[y].split(',')[0].replace(/\D/g,''))
    }
    let result = Object.fromEntries(titles.map((_, i) => [ titles[i], prices[i]]));
    result = Object.entries(result)
    console.log(result)
    return result
}

module.exports.scrapeChannel = async function (url) {
    console.log(scrape)
    let allProducts = [];
    const browser = await puppeteer.launch({
        headless: true,
    });

    const page = await browser.newPage();
    page.setDefaultNavigationTimeout(90000);
    await page.addStyleTag({ content: "{scroll-behavior: auto !important;}" });
    await page.setUserAgent('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36');
    await page.setDefaultNavigationTimeout(0);
    await page.goto(url);
    while (await page.$("#product-list > div.paging > a.paging-next.selenium-WC-paging-next-button")) {
    await page.evaluate(scrape).then(async el => {
        try {
                if (await page.$('#onetrust-accept-btn-handler')) {
                    await page.click('#onetrust-accept-btn-handler')
                    await page.waitFor(1500)
                }
                let products = await iterateProducts(el[1], el[0])
                allProducts = products.concat(allProducts)
                await page.waitFor(1000)
                await page.click('#product-list > div.paging > a.paging-next.selenium-WC-paging-next-button')
                await page.waitForNavigation();
        } catch (error) {
            console.log('errrrr!!!!!!!!!!', error)
        }
    })}
    allProducts = allProducts.sort((a, b) => a[1] - b[1])
    return allProducts
}

【问题讨论】:

  • @Marc 主帖已更新

标签: node.js module puppeteer module.exports


【解决方案1】:

您会收到该错误,因为在声明 scrapeChannel 时,未定义 scrape。所以,当你调用scrapeChannel 时,scrape 仍然没有在函数闭包内部定义。你可以在这里阅读更多关于 javascript 闭包的信息https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

您不应该依赖在其他文件上声明的变量而不导入它们。

如果您想在scrapeChannel 中引用scrape 函数,我会推荐以下任一选项:

const scrape = module.exports.scrape = () => {}
module.exports.scrapeChannel = () => {scrape();}
module.exports.scrape = () => {}
module.exports.scrapeChannel = () => {module.exports.scrape();}

【讨论】:

    【解决方案2】:

    this 添加到scrapeiterateProducts 解决了这个问题。但是如果有人能解释为什么需要this

    await page.evaluate(this.scrape)
    let products = await this.iterateProducts(el[1], el[0])
    

    【讨论】:

    • 可能是因为module.exports 是一个对象,所以您试图从附加到该对象的函数中访问该对象的另一个属性。如果没有this,您可能要求的是全局scrape。使用this,您正在请求module.exports 上的房产。您可以(应该!)将您的代码简化为一个传达相同基本行为的更简单示例:module.exports = {foo: function () {}, bar: function () {console.log(/*this.*/foo)}}
    猜你喜欢
    • 2019-09-29
    • 2012-05-14
    • 2018-09-06
    • 1970-01-01
    • 2021-04-22
    • 1970-01-01
    • 2017-03-17
    • 1970-01-01
    相关资源
    最近更新 更多