代码之家  ›  专栏  ›  技术社区  ›  noone

如何处理大量带有全部承诺的请求

  •  1
  • noone  · 技术社区  · 5 年前

    我有大约5000个链接,我需要爬行所有这些链接。所以我想知道有没有比这更好的方法。这是我的密码。

    let urls = [ 5000 urls go here ];
    
    const doms = await getDoms(urls);
    
    // processing and storing the doms
    
    getDoms = (urls) => {
    
      let data = await Promise.all(urls.map(url => {
        return getSiteCrawlPromise(url)
      }));
      return data;
    
    }
    
    getSiteCrawlPromise = (url) => {
    
      return new Promise((resolve, reject) => {
        let j = request.jar();
        request.get({url: url, jar: j}, function(err, response, body) {
            if(err)
              return resolve({ body: null, jar: j, error: err});
            return resolve({body: body, jar: j, error: null});
        });
      })
    
    } 
    

    是否有一种机制在Promise中实现,以便将作业划分为多个线程和进程。然后返回整个输出? 我不想将URL划分成更小的片段并处理这些片段

    2 回复  |  直到 5 年前
        1
  •  2
  •   PrashanD    5 年前

    Promise对象表示异步操作的最终完成(或失败)及其结果值。

    没有内置机制承诺“将作业划分为多个线程和进程”。如果必须这样做,则必须将URL数组拆分为较小的数组,并将拆分的数组同时排队到单独的爬行器实例上。

    但是,完全没有必要这样做,因为您使用的是node js和node crawler,所以可以使用 maxConnections 节点爬虫的选项。 这就是它建造的目的 最终结果是一样的。您将在多个线程上对URL进行爬行,而不会浪费时间和精力手动分块和处理多个爬行器实例,或者依赖于任何并发库。

        2
  •  1
  •   Elliot Nelson    5 年前

    至少现在还没有这种机制内置到JavaScript中。

    您可以使用提供更多功能的第三方承诺库,例如 Bluebird ,您可以在其中使用它们的并发功能:

    const Promise = require('bluebird');
    
    // Crawl all URLs, with 10 concurrent "threads".
    Promise.map(arrayOfUrls, url => {
        return /* promise for crawling the url */;
    }, { concurrency: 10 });
    

    另一种选择是使用专用的节流库(我强烈建议 bottleneck ,这允许您表示任何一般类型的速率限制。这种情况下的语法将类似于您已有的语法:

    const Bottleneck = require('bottleneck');
    const limit = new Bottleneck({ maxConcurrent: 10 });
    
    const getCallSitePromise = limit.wrap(url => {
        // the body of your getCallSitePromise function, as normal
    });
    
    // getDoms stays exactly the same
    

    可以 你自己解决这个问题,但带一个(或两个都带!)上面的库中的一个可以为您节省大量的代码。