如何在Node.js中同步使用request?

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

这是我非常基本的脚本,用于抓取给定的 URL 并获取其中的所有链接。 我想在请求功能完成后打印

links_arr
。但是,这里执行了请求回调函数,因此,我打印了一个空数组。我如何同步执行此操作?即按以下顺序。

  1. 请求 URL。
  2. Cheerio 获取所有链接。
  3. 我们循环遍历所有项目,并将它们插入到 links_arr 数组中。
  4. 打印数组。

附注我知道 Node.js 用于异步任务,但这是我需要满足的要求。我读到像 Promises 这样的东西可以在这方面帮助我,但是,由于我没有 Node 的高级知识,所以我不知道如何实现它。一些帮助将不胜感激。 我使用 Request 库进行 http 请求,使用 url 进行 url 解析,使用 cheerio 进行 html 解析。

var request = require('request');
var cheerio = require('cheerio');
var url = require('url');
var all_links = [];
var processing = [];
var processed = [];
var base_url = "https://www.npmjs.com";
var base_host = "www.npmjs.com";


var analyze_href_sync = function(u){
    console.log("Analysing URL "+u);
    url_obj = url.parse(u);
    url_formatted = url.format(url_obj);
    if (!url_obj.host) {
        //Relative URL
        resolved_url = url.resolve(base_url, url_formatted);
        return resolved_url;
    } else if (url_obj.protocol.startsWith("http")){
        if (url_obj.host == base_host) {
            return url_formatted;
        } else {
            return false;
        }
    } else {
        return false;
    }
}

var scrape_all_links_sync = function(u){
    console.log("Scraping all links from URL "+u);
    var links_arr = [];
    request(u, function(err, res, body){
        $ = cheerio.load(body);
        links = $('a');
        $(links).each(function(i, link){
            href = $(link).attr('href');
            console.log(href);
            links_arr.push(href);
        });
    });

    console.log(links_arr); //Need to print this, after the above request loopo is complete. i.e. After the array is filled.
}

var store_into_csv_sync = function(u){

}

var insert_into_processing_sync = function(u){

}

var remove_from_processing_sync = function(u){

}

var main = function(u){
    var analyze_url = analyze_href_sync(u);
    if (analyze_url != false) {
        scrape_all_links_sync(analyze_url);
    }
}

main(base_url);

上述脚本的输出是

Analysing URL https://www.npmjs.com
Scraping all links from URL https://www.npmjs.com/
[]
...
*All the other links found*
javascript node.js callback promise
3个回答
2
投票

您需要将

console.log(links_arr);
放入回调函数中:

var scrape_all_links_sync = function(u){
console.log("Scraping all links from URL "+u);
var links_arr = [];
request(u, function(err, res, body){
    $ = cheerio.load(body);
    links = $('a');
    $(links).each(function(i, link){
        href = $(link).attr('href');
        console.log(href);
        links_arr.push(href);
    });
    console.log(links_arr); //Need to print this, after the above request loop is complete. i.e. After the array is filled.
  });
}

所以只需将语句移动 1 行就可以了。

在 JavaScript 中,我们有 3 种处理异步代码的方法:

  1. 回调
  2. 承诺
  3. 基于发电机

因此您可以选择使用哪一个,也可以混合使用它们(例如取决于您使用的库)。您可以在此处阅读更多信息


1
投票
$(links).each(function(i, link){
            href = $(link).attr('href');
            console.log(href);
            links_arr.push(href);
     if(i==links.length-1)
        console.log(links_arr);  
        });

0
投票

2023 年,我写了 sync-request-curl。该库将帮助使用 libcurl 的 Easy 界面发送同步 HTTP 请求。

该库包含原始 sync-request 中功能的子集,但利用 node-libcurl 以获得更好的性能和 NodeJS 的附加 libcurl 选项。

这是 GET 请求的基本用例:

// import request from 'sync-request-curl';
const request = require('sync-request-curl');
const response = request('GET', 'https://ipinfo.io/json');
console.log('Status Code:', response.statusCode);
console.log('body:', response.body.toString());
console.log('json:', JSON.parse(response.body.toString());

关于您的用例,您可以按如下方式重写代码:

const request = require('sync-request-curl');
const cheerio = require('cheerio');
const url = require('url');

const base_url = "https://www.npmjs.com";
const base_host = "www.npmjs.com";

const analyzeHrefSync = (u) => {
  console.log("Analyzing URL " + u);
  const url_obj = new URL(u);
  const url_formatted = url.format(url_obj);

  if (!url_obj.host) {
    return url.resolve(base_url, url_formatted);
  }
  if (url_obj.protocol.startsWith("http") && url_obj.host === base_host) {
    return url_formatted;
  }
  return false;
};

const scrapeAllLinksSync = (u) => {
  console.log("Scraping all links from URL " + u);
  const response = request('GET', u);
  const body = response.body.toString();

  const $ = cheerio.load(body);
  const links = $('a');
  const linksArr = [];

  $(links).each(function (i, link) {
    const href = $(link).attr('href');
    console.log(href);
    linksArr.push(href);
  });

  console.log(linksArr);
};

const main = function (u) {
  const analyzeUrl = analyzeHrefSync(u);
  if (analyzeUrl !== false) {
    scrapeAllLinksSync(analyzeUrl);
  }
};

main(base_url);

当使用

node index.js
运行时,会给我们预期的结果:

希望这有帮助:)

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.