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

时间:2019-02-07 15:28:19

标签: node.js request web-crawler es6-promise

我大约有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中实现的机制,因此可以将作业分配到多个线程和进程。然后整体返回输出? 而且我不想将网址分成较小的片段并处理这些片段

2 个答案:

答案 0 :(得分:2)

  

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

Promise中没有内置的机制来“将作业分为多个线程和进程”。如果必须这样做,则必须将urls数组分段为较小的数组,并将分段后的数组同时排队到单独的搜寻器实例上。

但是,绝对不需要这样做,因为您使用的是node-js和node-crawler,因此可以使用node-crawler的maxConnections选项。 这就是它的构建目的,最终结果将是相同的。您将在多个线程上搜寻url,而不会在手动分块和处理多个搜寻器实例上浪费时间和精力,也不必依赖任何并发库。

答案 1 :(得分:1)

至少到现在,Java尚未内置这种机制。

您可以使用提供更多功能的第三方Promise库,例如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

可以自己解决此问题,但是带上一个(或两个!)库将为您节省很多代码。