使用setIntervalAsync启动和重新启动异步函数返回TypeError无法将未定义或null转换为对象

问题描述 投票:0回答:1

我一直在尝试实现一个Web抓取工具,该抓取工具将使用从MongoDB中提取的数据来创建一组URL,以定期使用puppeteer进行抓取。我一直在尝试使用setIntervalAsync使我的刮板功能定期进行刮板。

这里是我的代码,现在抛出“ UnhandledPromiseRejectionWarning:TypeError:无法将未定义或null转换为Function.values上的对象...”

puppeteer.js

 async function scrape(array){      
            // initialize for loop here
            let port = '9052'
            if(localStorage.getItem('scrapeRunning')=='restart'){
                clearIntervalAsync(scrape)
                localStorage.setItem('scrapeRunning') == 'go'
            }else if(localStorage.getItem('scrapeRunning') != 'restart'){
            /// Puppeteer scrapes urls in array here ///
}

server.js

app.post('/submit-form', [
        // Form Validation Here //
    ], (req,res)=>{

        async function submitForm(amazonUrl,desiredPrice,email){
            // Connect to MongoDB and update entry or create new entry
            // with post request data
            createMongo.newConnectToMongo(amazonUrl,desiredPrice,email)
            .then(()=>{
                // Set local variable that will alert scraper to clearIntervalAsync///
                localStorage.setItem('scrapeRunning','restart');
                // before pulling the new updated mongoDB data ...
                return createMongo.pullMongoArray();

            })
            .then((result)=>{
                // and start scraping again with the new data
                puppeteer.scrape(result)
            })
        submitForm(req.body.amazonUrl, req.body.desiredPrice,req.body.email);
     }
}

createMongo.pullMongoArray()
.then((result)=>{
    setIntervalAsync(puppeteer.scrape, 10000, result);
})

当前,刮板在启动服务器后将按预期方式启动,并且在刮板结束与再次开始之间保持10秒钟的时间。一旦有帖子提交,MongoDB集合将使用帖子数据进行更新,则将创建localStorage项,但是scrape函数将脱离常规并引发typeError。我不知道发生了什么,并尝试了多种方法来解决此问题(包括将setIntervalAsync和clearIntervalAsync保留在请求后代码块中),但到目前为止仍未成功。我对编码有些陌生,并且对异步代码非常缺乏经验,因此,如果有人对这种问题有任何经验,并且可以对正在发生的事情有所了解,我将不胜感激!

我只认为它与异步有关,无论我尝试过什么,它似乎也在newConnectToMongo函数完成之前运行pullMongoArray函数。

javascript express asynchronous setinterval clearinterval
1个回答
0
投票

经过几个小时的搜索,我认为我可能已经找到了可行的解决方案。我已经完全取消了localStorage的使用,并从scrape函数中删除了if和else if语句。我还制作了一个全局计时器变量,并向该文件添加了控制功能。

puppeteer.js

let timer;

function start(result){
    timer = setIntervalAsync(scrape,4000, result)
}

function stop(){
    clearIntervalAsync(timer)
}


async function scrape(array){       
        // initialize for loop here
        let port = '9052'
        // Puppeteer scrapes urls from array here //
}

我已经稍微修改了服务器代码,因此在服务器启动时,它会从MongoDB获取结果,并将其用于刮板启动功能。在更新MongoDB之前,发布请求还调用stop函数,从MongoDB中获取新结果,然后调用start scraper函数。

server.js

createMongo.pullMongoArray()
.then((result)=>{
    puppeteer.start(result);
})

app.post('/submit-form', [
        // Form Validation In Here //
    ], (req,res)=>{

        async function submitForm(amazonUrl,desiredPrice,email){
            // Stop the current instance of the scrape function
            puppeteer.stop();
            // Connect to MongoDB and update entry or create new entry
            // with post request data
            createMongo.newConnectToMongo(amazonUrl,desiredPrice,email)
            .then(()=>{
                // before pulling the new updated mongoDB data ...
                console.log('Pulling New Array');
                return createMongo.pullMongoArray();
            })
            .then((result)=>{
                // and restarting the repeating scrape function
                puppeteer.start(result);
            })
      }
})
© www.soinside.com 2019 - 2024. All rights reserved.