如何限制Express.js中的调用数?

如何限制Express.js中的调用数?,express,promise,puppeteer,Express,Promise,Puppeteer,我正在使用express来显示与木偶演员一起进行网络抓取的结果,但我有一个性能问题 我多次调用scraper文件,因为我想一次得到多个结果 例如: const express = require('express') const app = express() const scraper = require('./scrapers/scraper.js'); app.get('/getResults', function(req, res, next) { const url = 'htt

我正在使用express来显示与木偶演员一起进行网络抓取的结果,但我有一个性能问题

我多次调用scraper文件,因为我想一次得到多个结果

例如:

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,依此类推

事实上,我的代码调用scraper文件18次,这对计算机性能不好,因为Puppeter是基于Chromium的,它一次打开一个新的Chromium实例18次

我甚至在运行它时会出现以下错误:

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

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

val1.then(v1=>返回val2.then(v2=>{…})
您应该打开一个新的Chromium选项卡,而不是实例。(你刚才混淆了概念吗?)

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

你也许能找到一些包裹。如果没有什么适合您的,请记住,当有东西出来时,Node不会注意到过程的结束,请处理这种情况

我可以互换使用以下方法:

  • 将URL标记为正在下载,如果在给定时间内未检索到,则返回队列(更具体地说:指定何时重新下载URL。下载时为+1分钟,下载后为1个月)
  • 我保存下载过程的PID,并定期检查它是否正常工作
还有控制HTTP调用数量的速率限制。在端点上,在IP的同时订单数上。

async await 您可以使用async Wait编写代码。有趣的是,您可以处理所有错误,并自动返回带有承诺的值

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)
 }
})
对于…的循环 您可以优化这些代码并减少代码重复。使用async..wait和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循环实现了这一点,多亏了它,现在我的代码行减少了。祝你有一个愉快的一天:)你也可以用其他两种方法做同样的事情,我只是展示了不同的方法,请随意探索。
// 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)