Как вручную приостановить и выполнить для пакета записей, используя карту и обещания в JavaScript? - PullRequest
0 голосов
/ 28 октября 2019
function sleep(ms) {
  var start = new Date().getTime(),
    expire = start + ms;
  while (new Date().getTime() < expire) {}
  return;
}

async function executeWithDelay(offers) {
  return Promise.all(
    offers.map((offer, i) =>
      getDetailedInfo(offer).then(data => {
        offer = data;
        if (i % 5 === 0) {
          console.log('executed but it delays now for 3 seconds');
          sleep(3000);
        }
      })
    )
  ).then(function(data) {
    return offers;
  });
}

Попытка добиться соскоба с использованием наилучшего возможного решения. Я объединяю cheerio и puppeteer вместе, и у меня есть хороший код для отладки. Приведенный выше код работает нормально, если данные предложения меньше, т.е. 5-10 записей. Если он превышает, браузер выходит из строя, хотя я работаю в безголовой версии.

Это в основном из-за внутренней ошибки пакета, которую я использую, которая не может справиться с нагрузкой. Мой эксперимент состоит в том, чтобы немного задержать каждую партию записей и завершить полное выполнение записей.

Но с приведенным ниже кодом он ведет себя как неблокирующий код, и в первый раз он задерживается и выполняется постоянно.

Должен ли я использовать цикл вместо карты или есть альтернатива для решения этой ситуации?

1 Ответ

0 голосов
/ 28 октября 2019

Вы никогда не захотите "спать" с таким циклом ожидания-ожидания. Это означает, что больше ничего нельзя сделать в главном потоке.

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

Другая проблема с этим кодом заключается в том, что вы возвращаете offers, а не результаты вызова getExtendedInfo.

Если проблема вызывается getExtendedInfo слишком часто, вы можете вставить задержку (используя setTimeout, а не занятый цикл). Например, это делает первый запрос к getExtendedInfo почти сразу, следующий через одну секунду, следующий через две секунды и так далее:

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

function executeWithDelay(offers) {
  return Promise.all(
    offers.map((offer, i) =>
      sleep(i * 1000).then(getDetailedInfo)
    )
  });
}

Очевидно, что вы можете отрегулировать эту задержку по мере необходимости.

(Обратите внимание, что executeWithDelay не объявлено async; в этом нет необходимости, поскольку в любом случае необходимо использовать Promise.all.)

...