Как ограничить количество звонков в Express.js? - PullRequest
0 голосов
/ 29 марта 2019

Я использую экспресс для показа результата от некоторой работы в Интернете с кукловодом, но у меня проблема с производительностью.

Я несколько раз вызываю файл скребка, потому что хочу получить несколько результатов одновременно.

Например:

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 раз, и это не очень хорошо для производительности компьютера, поскольку кукловод основан на Chromium и буквально 18 раз открывает новый экземпляр Chromium.

Я даже получаю эту ошибку при запуске:

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

Ответы [ 2 ]

1 голос
/ 29 марта 2019

async await

Вы можете написать свой код с помощью async await.Самое интересное, что вы можете обрабатывать все ошибки, и значение возвращается автоматически с обещаниями.

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-limit

Вы можете использовать пакет с именем 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 loop

Вы можете оптимизировать эти коды и уменьшить дублирование кода.С 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)
0 голосов
/ 29 марта 2019

Знаете ли вы, что обещания можно давать последовательно?

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

Вы должны открыть новую вкладку Chromium, а не экземпляр. (Вы только что перепутали понятия?)

И самое главное - вам нужно лучше управлять процессами загрузки. Очередь будет лучшей здесь. Это может быть просто: это гарантирует, что не более чем n запущенных процессов или более продвинутых: это контролирует ресурсы сервера.

Возможно, вы сможете найти какой-нибудь пакет. Если вам ничего не подходит, не забудьте разобраться с ситуацией, когда что-то вылезет, и Node не заметит окончания процесса.

Я использую методы взаимозаменяемо:

  • помечает URL как загруженный, и если он не получен в течение заданного времени, он возвращается в очередь (более конкретно: укажите, когда следует повторно загружать URL. В момент загрузки он составляет +1 минуту, после загрузки например, 1 месяц)
  • Я сохраняю PID процесса загрузки и периодически проверяю, работает ли он

Есть также rate-limits, которые контролируют количество HTTP-вызовов. На конечной точке, по количеству одновременных заказов с IP.

...