【问题标题】:NodeJS - How to run request-promise synchronously?NodeJS - 如何同步运行请求承诺?
【发布时间】:2020-03-22 18:35:10
【问题描述】:

首先我有两个函数我在该循环中有一个 for 循环我正在调用第二个具有请求承诺的函数。我担心的是,当循环正在执行并调用第二个函数它没有等待 request-promise 完成,循环接下来会迭代并再次调用第二个函数。 我希望先完成 request-promise,然后再完成循环的下一次迭代。那我该怎么做呢?为了简单起见,我粘贴了第一个和第二个函数的代码 sn-ps

第一个功能码sn-p


for (let i = 0; i < len; ++i) {
    var url_ = "https://www.someurl****.com" + allUrls_ + urlLastParam + (i + 1).toString();
    console.log(allUrls_);
    console.log('getValues URL: ' + url_);
    getValues(res, url_, allUrls_)
}

第二个功能

const rp = require('request-promise');
const cheerio = require('cheerio');

function getValues(res, url_, allUrls_) {
    let options = {
        uri: url_,
        transform: function (body) {
            return cheerio.load(body);
        }
    };
    console.log('inside getValues');
    rp(options)
        .then(function ($) {
            console.log('inside getValues function request');
            $('.some-selector').map(function (i, links) {
                // my custom code
            })
        })
        .catch(function (err) {
            // catch errors
        })
}

【问题讨论】:

    标签: node.js web-scraping request cheerio


    【解决方案1】:

    如果您从getValues() 返回承诺,那么您可以在for 循环中使用async/await 来暂停每次调用getValues() 的循环,并将它们顺序排列为一个接一个而不是全部同时运行:

    const rp = require('request-promise');
    const cheerio = require('cheerio');
    
    function getValues(res, url_, allUrls_) {
        let options = {
            uri: url_,
            transform: function (body) {
                return cheerio.load(body);
            }
        };
        console.log('inside getValues');
        return rp(options).then(function($) {               // return promise here
            console.log('inside getValues function request');
    

    欢呼在这里 $('.some-selector').map(function (i, links) { // 我的自定义代码 }) 归还东西; // 大概在这里返回一些东西 }); }

    async function process() {
        try {
            for (let i = 0; i < len; ++i) {
                var url_ = "https://www.someurl****.com" + allUrls_ + urlLastParam + (i + 1).toString();
                console.log(allUrls_);
                console.log('getValues URL: ' + url_);
                let value = await getValues(res, url_, allUrls_);     // await here
            } catch(e) {
                console.log(e);
                // handle any error that occurred in getValues()
            }
        }
    }
    

    仅供参考,$('.some-selector') 将无法按照您在此代码中的方式工作。 $ 是您的 HTML。您必须先将 html 内容加载到cheerio 中,然后才能执行此操作(我已将其添加到我的答案中)。

    【讨论】:

    • 非常感谢!它起作用了,但它没有刮掉超过 2 页 IDK 的原因。不过还是谢谢。
    • @AjayKumar - 好吧,也许你的for 循环并没有完全按照不同的URL 做它应该做的事情。我不知道你想在那里做什么,而且那里没有真正的 URL,所以我无法真正查看它。
    • 谢谢!为了快速回复,这是我的项目链接github.com/AjayKrP/scraper看看
    • @AjayKumar - 好吧,我没有意识到您已经在 request-promise 中运行 cheerio.load() 作为转换选项。您可以删除我添加的cheerio.load()。我会更新我的答案。
    • @AjayKumar - 就只处理 2 个页面而言,您只需要调试它。从getAllUrls() 获得多少链接开始。然后,看看getPageUrlAndLength()allUrls.forEach() 循环中被调用了多少次。然后,查看在process() 内部调用了多少次getValues() 等等。您应该能够跟随流程,看看它在哪里没有按照您的预期进行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-09
    • 1970-01-01
    • 2020-06-16
    • 2018-12-31
    • 2021-04-19
    • 2017-10-24
    相关资源
    最近更新 更多