Почему Node висит на выходе этого скрипта с большим количеством обещаний? - PullRequest
0 голосов
/ 12 декабря 2018

Я создавал прототип сценария, который будет использоваться для целей тестирования, который будет последовательно запускать достаточное количество http-запросов и будет продолжаться, несмотря на любые ошибки на этом пути.(Кроме того, это был отличный способ играть с глубокой рекурсией без переполнения стека вызовов.)

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

#!/usr/bin/env node

const requests = [...Array(100000).keys()];

const rejection = arg => new Promise((_, reject) => reject(arg));

function handleFailureAndContinue() {
  if (requests.length > 0) {
    return rejection(requests.pop())
      .then(undefined, handleFailureAndContinue);
  } else {
    console.log('finish: ' + new Date().toISOString());
  }
}

console.log('start:  ' + new Date().toISOString());

rejection(requests.pop())
  .then(undefined, handleFailureAndContinue);

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

Затем я запустил эту команду, чтобы рассчитать время и посмотреть, сколько времени потребовался фактический код для запуска и сколько вращался узел, пока он не вышел.

# This was on a Mac, so you'll want to use date instead of gdate on Linux.
./promiseTest.js && printf "exit:   " && TZ=Zulu gdate -Ins

Вот результаты.

start:  2018-12-11T23:49:06.282Z
finish: 2018-12-11T23:49:06.396Z
exit:   2018-12-11T23:50:00,370138000+00:00

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

Как я могу понять, почему это происходит, икак я могу избежать этого?

1 Ответ

0 голосов
/ 12 декабря 2018

Я думаю, что узел не получил сигнал о том, что цепочка завершена, тогда сценарий существует, когда время истекло.Пара вещей:

  1. Удалите параметр '_' из вызова функции Promise
  2. Удалите неопределенное значение как параметр из .then() функций
  3. Добавьтеверните в условие else handleFailureAndContinue(), чтобы функция всегда закрывалась и не вешала цепочку.код для:
        #!/usr/bin/env node
        const requests = [...Array(100000).keys()];
    
        const rejection = arg => new Promise((reject) => reject(arg));
    
        function handleFailureAndContinue() {
          if (requests.length > 0) {
            return rejection(requests.pop())
              .then(handleFailureAndContinue);
          } else {
            console.log('finish: ' + new Date().toISOString());
            return
          }
        }
    
        console.log('start:  ' + new Date().toISOString());
    
        rejection(requests.pop())
         .then(handleFailureAndContinue)
         .catch(e => console.error(e));
    
...