【问题标题】:Looping over query results in Node, but I keep losing my loop?在Node中循环查询结果,但我一直丢失我的循环?
【发布时间】:2020-10-02 01:52:28
【问题描述】:

背景知识:我正在构建一个工具,可以按计划截取网页截图。它还存储了有关如何截取屏幕截图的设置(例如,隐藏某些页面元素,等待 X 秒以防长轮询请求或具有动画的启动页面)

很自然,我必须从数据库中读取这些内容,然后循环这些结果以运行基于这些变量的代码块。

我可以很好地输出我的记录。我可以单独遍历它们就好了。但是当我尝试插入并播放现有的代码块时,事情就崩溃了。不知何故,这打破了我的循环,页面下方的代码无法识别我的数据库循环中的变量。

假设我的数据库记录被分配给变量poo,并且在此之前我对自己的语法有信心:

for (var i = 0; i < poo.length; i++) {
    console.log('The name of this task is ' + poo[i].PrettyName); 

    //So far so good! I can output my column names as variables and do what I want with them.

    Screenshot(poo[i].URL);  
    //This works too!

    async function Screenshot(url) {
    const browser = await puppeteer.launch({
   headless: true,
   defaultViewport: {width: 1920, height: 1080},
   args: [
   "--no-sandbox",
   "--disable-gpu",
   ]
 });

//This is not the end of my code, but basically nothing after this point works. 
//When I try to read or log any variable, 
//even ones that worked before, it tells me "cannot read property ___ of undefined."

我是否不小心在某处用括号破坏了循环?这是异步函数魔法吗?当我必须应用回调时有什么误解?

即使我在异步函数运行之前手动输入了 10 秒的延迟,变量仍然会中断,这应该足以形成一个记录集进行处理。

你看到的代码的肉和土豆是puppeteer模块。

【问题讨论】:

    标签: javascript node.js puppeteer node-modules


    【解决方案1】:

    我和你有同样的问题。我在每个 mq 任务中调用 screenshot 函数。所以当有很多任务同时执行时,会创建很多Chromium进程。我的函数在这里:

    module.exports = async (_browser, sheetJson) => {
        const browser = await puppeteer.launch({args: ['--no-sandbox']});
        const page = await browser.newPage();
        //goto.page
        const thumbnailPath = path.join('test/out', shortId() + '.png');
        await page.screenshot({
            path: thumbnailPath,
            fullPage: true,
        });
        await page.close();
        await browser.close();
        return thumbnailPath;
    }
    
    

    我认为Chromium进程太多会导致内存泄漏。因为每个mq任务都会创建一个浏览器实例。所以我尝试创建一个glob浏览器实例。而且我觉得行得通,只有大约五个 Chromium 进程。

    【讨论】:

      【解决方案2】:

      确实基于当前共享的示例,您的怀疑是正确的:您错过了两者的右括号:(1) Screenshot() 函数和 (2) for 循环。

      修复它们的示例:

      const poo = [
        { PrettyName: 'one', URL: 'https://google.com' },
        { PrettyName: 'two', URL: 'https://google.fr' }
      ];
      
      for (var i = 0; i < poo.length; i++) {
        console.log('The name of this task is ' + poo[i].PrettyName);
        Screenshot(poo[i].URL);
      
        async function Screenshot(url) {
          const browser = await puppeteer.launch({
            headless: true,
            defaultViewport: { width: 1920, height: 1080 },
            args: ['--no-sandbox', '--disable-gpu']
          });
           // puppeteer methods goes here
        } // ⚠️ closes Screenshot()
      }  // ⚠️ closes for loop
      
      console.log('Loop ended succesfully');
      

      按预期运行。

      输出:

      The name of this task is one
      The name of this task is two
      Loop ended succesfully
      

      注意:当然,代码中还可能存在其他大括号问题,但这需要minimal, reproducible example 中的大部分代码才能说明。

      【讨论】:

      • 很抱歉没有足够清楚地表达这一点 - 我的代码并没有到此结束。那时它刚刚停止工作,所以这就是我粘贴的全部内容。其他功能在页面下方正确关闭。我找到了自己的答案,其中涉及使用let 而不是var,以便我的变量持续存在。
      • 感谢更新!很清楚,很高兴您发现了问题。实际上,最好在 Node 中的任何地方使用 ES6 特性——比如 letconst,这样可以防止多个问题。如果你有时对代码块不确定——而且你还没有使用它——我建议使用 JS linter(如 ESlint 或 JSlint),它可以为你捕获很多语法错误。如果您使用var,也可以设置为通知您。
      【解决方案3】:

      感谢 Reddit 用户 kranker,在我的 Google 旅程中找到 a solution

      在循环中创建的任何闭包中,let 变量将绑定到仅来自该循环迭代的值,而 var 变量将是变量的当前值。

      必须将var 更改为let

      for (let i = 0; i < poo.length; i++)
      

      现在我的变量在页面下方一直保持正常,我的脚本可以一次处理多个事情。

      【讨论】:

        【解决方案4】:

        我认为您在代码中犯了一个小错误:

        for (var i = 0; i < poo.length; i++) {
            console.log('The name of this task is ' + poo[i].PrettyName); 
        
            //So far so good! I can output my column names as variables and do what I want with them.
        
            Screenshot(poo[i].URL);  
            //This works too!
        
            async function Screenshot(url) {
            const browser = await puppeteer.launch({
           headless: true,
           defaultViewport: {width: 1920, height: 1080},
           args: [
           "--no-sandbox",
           "--disable-gpu",
           ]
         });
        //^
        

        您可能不小心将); 放在了循环的末尾。

        【讨论】:

        • 不,先生,您指出的是关闭puppeteer.launch 功能。整个块正在启动一个浏览器,以便在循环的后面提供命令。删除它会导致语法错误。
        猜你喜欢
        • 2017-05-22
        • 2012-09-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-20
        • 2016-01-17
        相关资源
        最近更新 更多