Nano Hash - криптовалюты, майнинг, программирование

async/await: разрешение Promise.all() партиями по N

tl;dr Нужна помощь с промисами.

Вот небольшая функция скребка, которая лежит в основе всего этого:

function request(method, url) {
    return new Promise(function (resolve, reject) {
        var xhr = new XMLHttpRequest();
        xhr.open(method, url);
        xhr.onload = resolve;
        xhr.onerror = reject;
        xhr.send();
    });
}

У меня также есть довольно большой список профилей, которые я хотел бы решить:

const profiles = ['http://www.somesite.com/profile/1',
'http://www.somesite.com/profile/2'] // 100+ more

Как мне обрабатывать их партиями, скажем, по 5 за раз?

Вот мой мыслительный процесс:

  1. Разделить на части N с помощью _.chunk()
  2. Await Promise.all() разрешает указанный фрагмент

Вот что у меня есть до сих пор:

async function processProfileBatch(batchOfUrls) {
    let promises = [];

    // Populate promises
    for (let i = 0; i < batchOfUrls.length; i++) {
        let url = batchOfUrls[i]
        promises.push(request('GET', url))
    }

    // Wait for .all to resolve
    return await Promise.all(promises)
}
const profileBatches = _.chunk(profileLinks, 3)
for (let i = 0; i < profileBatches.length; i++) {
        let processedBatch = await processProfileBatch(profileBatches[i])
        console.log(new Date(), 'processedBatch', processedBatch);
    }

К сожалению, это просто возвращает ProgressEvents; при проверке xhr, содержащегося внутри, имеет .responseText значение «», хотя readyState равно 4:

введите здесь описание изображения


  • Вы можете использовать fetch вместо XMLHttpRequest. 02.06.2018
  • @HRM Невозможно использовать выборку - целевой сайт чувствителен к файлам cookie / сеансам или чему-то еще. 02.06.2018
  • Получение ProgressEvent является нормальным для прослушивания onload, вы можете сделать xhr.onload = () => resolve(xhr) или что-то еще, чтобы получить другое значение результата 02.06.2018
  • Если responseText пусто, это, скорее всего, похоже на проблему SOP. 02.06.2018
  • @Берги Отрицательно; если я добавлю sleep(1000) в Promise.all(), чтобы это заняло немного больше времени, все обещания xhr разрешаются. Без его добавления иногда они разрешаются, а иногда нет. Такое ощущение, что я не могу запускать несколько XHR одновременно, хотя в этом нет никакого смысла... 02.06.2018
  • @ dsp_099 Какой сайт вы загружаете, может быть, он ограничивает количество запросов? И что такое statusCode ответов? 02.06.2018
  • Вы пытались получить с включенными учетными данными? fetch(url, { method: 'GET', credentials: 'include' }) 02.06.2018
  • @HMR Возможно ли, что консоль Chrome будет отображать пустую строку, хотя на самом деле там была большая строка? Я только что выполнил 10 одновременных xhrs и выборок, и все они вернули ожидаемые значения. 02.06.2018

Ответы:


1

Проблема с фрагментированием заключается в том, что у вас есть x активных запросов, а затем вы ждете, пока все они закончатся, чтобы начать следующее количество запросов x.

С помощью throttle вы можете постоянно иметь x активных запросов, пока все сделано.

//lib comes from: https://github.com/amsterdamharu/lib/blob/master/src/index.js
const lib = require("lib");

function processProfileBatch(batchOfUrls){
  const max10 = lib.throttle(10)
  return Promise.all(
    batchOfUrls.map(
      url=>
        max10(url=>request('GET', url))(url)
    )
  )
};

Если вы предпочитаете ограничивать соединения за период (скажем, 2 в секунду), а не ограничивать активные соединения, вы можете использовать ThrottlePeriod:

twoPerSecond = lib.throttlePeriod(2,1000);
... other code
twoPerSecond(url=>request('GET', url))(url)

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

//lib comes from: https://github.com/amsterdamharu/lib/blob/master/src/index.js
const lib = require("lib");

function processProfileBatch(batchOfUrls){
  const max10 = lib.throttle(10)
  return Promise.all(
    batchOfUrls.map(
      url=>
        max10(url=>request('GET', url))(url)
        .catch(err=>new lib.Fail([err,url]))
    )
  )
};

processProfileBatch(urls)
.then(//this does not reject because rejects are caught and return Fail object
  result=>{
    const successes = results.filter(lib.isNotFail);
    const failed = results.filter(lib.isFail);
  }
)
02.06.2018
  • Это аккуратно, дай мне подумать на секунду. Однако я заметил, что если я просто подожду немного дольше, все запросы разрешатся просто отлично. Другими словами, похоже, что Promise.all разрешается быстрее, чем должно, по какой-то необъяснимой причине. 02.06.2018
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..