【问题标题】:How to limit the number of calls in Express.js?如何限制 Express.js 中的调用次数?
【发布时间】:2019-03-29 12:15:14
【问题描述】:

我正在使用 express 来显示使用 puppeteer 进行网络抓取的结果,但我遇到了性能问题。

我多次调用刮板文件,因为我想一次获得多个结果。

例如:

const express = require('express')
const app = express()
const scraper = require('./scrapers/scraper.js');

app.get('/getResults', function(req, res, next) {
  const url = 'http://www.example.com';
    const val1 = new Promise((resolve, reject) => {
        scraper
            .getPrice(results, url, nights)
            .then(data => {
        resolve(data)
                })
        .catch(err => reject('Medium scrape failed'))
    })
  const url = 'http://www.example.com';
    const val2 = new Promise((resolve, reject) => {
        scraper
            .getPrice(results, url, nights)
            .then(data => {
        resolve(data)
                })
        .catch(err => reject('Medium scrape failed'))

  const url = 'http://www.example.com';
    const val3 = new Promise((resolve, reject) => {
        scraper
            .getPrice(results, url, nights)
            .then(data => {
        resolve(data)
                })
        .catch(err => reject('Medium scrape failed'))
  const url = 'http://www.example.com';
    const val4 = new Promise((resolve, reject) => {
        scraper
            .getPrice(results, url, nights)
            .then(data => {
        resolve(data)
                })
        .catch(err => reject('Medium scrape failed'))
  Promise.all([val1, val2, val3, val4])
    .then(data => {
        console.log(data)
    })
        .catch(err => res.status(500).send(err))
}

上面的代码会一次调用scraper.js 文件4次,但是我应该怎么做才能在前一个完成后调用每个文件呢?我的意思是,当 val1 完成后,它应该运行 val2 等等。

事实上,我的代码调用了刮板文件 18 次,这对计算机性能不利,因为 puppeteer 是基于 Chromium 的,它实际上一次打开一个新的 Chromium 实例 18 次。

当我运行它时,我什至得到了这个错误:

(node:26600) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 exit listeners added. Use emitter.setMaxListeners() to increase limit

【问题讨论】:

    标签: express promise puppeteer


    【解决方案1】:

    异步等待

    您可以使用异步等待编写代码。有趣的是,您可以处理所有错误,并通过 promise 自动返回值。

    app.get('/getResults', async function(req, res, next) { //<-- notice the async here
     try{
      const val1 = await scraper.getPrice(results, url, nights)
      const val2 = await scraper.getPrice(results, url, nights)
      const val3 = await scraper.getPrice(results, url, nights)
      const val4 = await scraper.getPrice(results, url, nights)
      return res.send([val1, val2, val3, val4])
     } catch(err) {
       res.status(500).send(err)
     }
    })
    

    p-限制

    您可以使用一个名为 p-limit 的包,它运行多个承诺返回和异步函数,但并发性有限。

    const pLimit = require('p-limit');
    
    const limit = pLimit(1);
    
    const input = [
        limit(() => scraper.getPrice(results, url, nights)),
        limit(() => scraper.getPrice(results, url, nights)),
        limit(() => scraper.getPrice(results, url, nights))
    ];
    
    (async () => {
        // Only one promise is run at once
        const result = await Promise.all(input);
        console.log(result);
    })();
    

    for..of 循环

    您可以优化这些代码并减少代码重复。使用 async..await 和 for..of,可以进一步减少代码,

    // assuming you have these urls
    const urls = [
     'http://example.com', 'http://example.com',  'http://example.com'
    ];
    
    const results = []
    for(let url of urls){
      const data = await scraper.getPrice(results, url, nights);
      results.push(data)
    }
    console.log(results)
    

    【讨论】:

    • 非常感谢您的帮助! for..of 循环起到了作用,现在我的代码行更少了。祝你有美好的一天:)
    • 其他两种方法你也可以这样做,我只是展示了不同的方法,请随意探索。
    【解决方案2】:

    你知道可以按顺序做出承诺吗?

    val1.then(v1 => return val2).then(v2=> {...})
    

    您应该打开一个新的 Chromium 选项卡,而不是实例。 (你是不是混淆了概念?)

    最重要的是 - 您需要更好地管理下载过程。这里的队列最好。可以很简单:确保运行的进程不超过n 或更高级:监控服务器资源。

    你也许能找到一些包裹。如果没有适合您的情况,请记住在出现问题时处理这种情况,Node 不会注意到该过程的结束。

    我交替使用方法:

    • 将URL标记为正在下载,如果在给定时间内没有检索到,则返回队列(更具体地说:指定何时重新下载URL。下载时为+1分钟,下载后例如 1 个月)
    • 我保存了下载过程的 PID 并定期检查它是否有效

    还有rate-limits控制HTTP调用次数。在端点上,在有 IP 的同时订单数上。

    【讨论】:

      猜你喜欢
      • 2015-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-31
      • 2017-07-04
      • 1970-01-01
      相关资源
      最近更新 更多