Недавно я столкнулся с проблемой программирования, связанной с параллелизмом, с некоторыми интересными результатами обучения асинхронному функциональному программированию в node.js.

Основная проблема заключалась в отправке набора запросов в json API, проверке общей длины ответа на запрос с разбивкой на страницы, запросе остальных страниц ответов на запрос и анализе этих ответов в единый объединенный вывод, при этом сводя к минимуму время, затрачиваемое на ожидание. для синхронных ответов HTTP.

Конкретная задача заключалась в том, чтобы выяснить, сколько футбольных матчей закончилось вничью в данном году. Для этого API был запрошен с количеством целей, на которые может быть привязана игра, от 0 до 10. Некоторые (но не все) из этих ответов были разбиты на страницы, поэтому необходимо было сделать несколько запросов, чтобы получить полные результаты. .

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

Хотя можно было бы использовать набор циклов for для синхронного выполнения каждого запроса, в конечном итоге это было бы довольно медленным. Вместо…

Чтобы получить общее количество игр, равных заданному счету:

  • Функция делает блокирующий запрос ожидания для количества игр с первой страницы результатов и количества страниц в результатах с разбивкой на страницы.
  • Общее число страниц ответа используется для создания массива целых чисел с фильтрацией первой страницы (во избежание избыточных сетевых запросов).
    e.x. ( 4-> [0,1,2,3] -> [1, 2, 3])
  • Этот целочисленный массив сопоставляется с массивом обещаний (все асинхронные функции возвращают тип обещания),
  • Этот массив промисов объединяется с промисами для подсчета из исходного запроса.
  • Блок кода использует Promise.all() для преобразования этого массива промисов в массив целых чисел.
  • И, наконец, он возвращает сумму этого массива с помощью функции сокращения().

Это дает количество игр с одинаковым счетом в данном году (например, количество игр в 2011 году, где team1goals=team2goals=1), но для полного результата нужны игры с одинаковым счетом по всем счетам от 0 до 10. Для этого :

  • Все результаты, по которым игры могут быть равными, отображаются в массив [0…10].
  • Этот массив целых чисел сопоставляется с массивом промисов.
  • Блок кода ожидает, пока Promise.all() преобразует этот массив промисов в массив целых чисел.
  • При разрешении результирующий массив целых чисел суммируется с помощью метода reduce(), чтобы получить итоговое значение.

Наконец, все это собрано во фрагменте ниже. Дайте мне знать, если вы обнаружите какие-либо проблемы или улучшения, которые нужно сделать!

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