Skip to content

Latest commit

 

History

History
162 lines (116 loc) · 10.8 KB

File metadata and controls

162 lines (116 loc) · 10.8 KB

Task for 22

Решить задачи на асинхронность

  • в репозитории прошлого задания сделать новую ветку
  • решить предложенный набор задач (и покрыть их тестами от 50%)
  • открыть PR с релеватными изменениямяи (без лишних задач)
  • сделать ревью 1 PR другого студента

Задачи

Promisify

Вам необходимо написать функцию promisify, которая преобразует функцию с колбэком в функцию, возвращающую промис. Это позволит работать с асинхронными функциями в современном стиле, используя промисы вместо колбэков.

Требования:

  • Функция promisify принимает на вход функцию, которая ожидает колбэк последним аргументом. Колбэк должен иметь стандартный вид: callback(error, result).
  • promisify возвращает новую функцию. При вызове эта функция возвращает промис, который:
    • Резолвится с результатом, если в колбэк передан null или undefined вместо ошибки.
    • Реджектится, если в колбэк передана ошибка.
  • Ваша функция должна корректно передавать все аргументы исходной функции, кроме колбэка.
// Пример функции на колбэках
function sum(a, b, cb) {
  setTimeout(() => {
    if (Math.random() < 0.5) {
      cb(null, a + b); // успех
    } else {
      cb("Ошибка"); // ошибка
    }
  }, 100);
}

// Преобразуем с помощью promisify
const promisifiedSum = promisify(sum);

promisifiedSum(2, 3)
  .then((result) => console.log(result)) // 5
  .catch((err) => console.log(err)); // "Ошибка"

Parallel

Реализуйте класс Parallel, который позволяет запускать несколько асинхронных задач (job) параллельно с ограничением на максимальное количество одновременно выполняющихся задач.

Требования:

  • Класс должен называться Parallel и быть конструктором (использоваться через new).

  • У экземпляра должны быть публичные методы:

    • job(fn) — добавляет задачу (функцию), которую нужно выполнить. Метод должен поддерживать чейнинг (возвращать сам объект).
    • done(cb) — запускает выполнение всех добавленных задач. Когда все задачи завершены, вызывает колбэк cb, передавая ему массив результатов.
  • Если не было добавлено ни одной задачи, done должен вызываться асинхронно.

  • Пока не вызван done, задачи не запускаются.

  • Если при создании объекта передать число (например, new Parallel(3)), оно задаёт максимальное количество задач, которые могут выполняться одновременно.

  • Все задачи — функции, которые принимают один аргумент: функцию-колбэк done(result), которую нужно вызвать по завершении задачи.

  • Результаты должны возвращаться в том же порядке, в котором были добавлены задачи.

  • Продумайте выполнение задач без простоев

const runner = new Parallel(2);

runner
  .job((done) => setTimeout(() => done("A"), 1000))
  .job((done) => setTimeout(() => done("B"), 500))
  .job((done) => setTimeout(() => done("C"), 300))
  .done((results) => {
    console.log(results); // ['A', 'B', 'C']
  });

fetchRetry

Реализуйте функцию fetchRetry, которая выполняет HTTP-запрос по заданному URL с помощью fetch и автоматически повторяет попытку в случае ошибки. Функция должна принимать три аргумента:

  • url — строка с адресом запроса.
  • retries — максимальное количество попыток (включая первую).
  • delay — задержка (в миллисекундах) между повторными попытками.

Если запрос завершается успешно, функция возвращает результат как обычный fetch. Если все попытки завершились неудачно, функция должна вернуть ошибку.

fetchRetry("https://dummyjson.com/products", 3, 1000)
  .then((response) => response.json())
  .then((data) => console.log(data))
  .catch((error) => console.error("Ошибка после всех попыток:", error));

Требования:

  • Если запрос завершился с ошибкой (например, сеть недоступна или получен некорректный HTTP-статус), функция должна подождать указанную задержку и попробовать снова, пока не исчерпает все попытки.
  • После успешного ответа функция должна вернуть результат без дополнительных попыток.
  • Если все попытки неудачны, функция должна вернуть ошибку.

debounce

Напишите функцию debounce, которая принимает два аргумента:

  • функцию, которую нужно вызывать (например, обработчик событий)
  • время задержки в миллисекундах

Функция debounce должна возвращать новую функцию-обёртку. Эта обёртка при каждом вызове не будет сразу запускать исходную функцию, а будет откладывать её выполнение на заданное количество миллисекунд. Если обёртку вызвать ещё раз до истечения задержки, предыдущий таймер отменяется и запускается новый отсчёт. В итоге исходная функция будет вызвана только один раз — спустя указанное время после последнего вызова обёртки

function onInput(event) {
  console.log("Запрос к серверу:", event.target.value);
}

const debouncedOnInput = debounce(onInput, 500);

inputElement.addEventListener("input", debouncedOnInput);

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

Что проверить:

  • Исходная функция вызывается не чаще одного раза за указанный интервал времени.
  • При частых вызовах обёртки исходная функция не запускается, пока не наступит "пауза".
  • Аргументы и контекст (this) корректно передаются в исходную функцию.

serialProcess

Напишите функцию serialProcess, которая принимает массив элементов и функцию-обработчик для каждого элемента. Обработчик должен вызываться для каждого элемента массива по очереди (строго по одному, не параллельно), и переходить к следующему элементу только после завершения обработки предыдущего.

Функция-обработчик вызывается с четырьмя аргументами:

  • el — текущий элемент массива,
  • index — индекс текущего элемента,
  • list — исходный массив,
  • done — функция, которую нужно вызвать по завершении обработки элемента, передав ей результат обработки.

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

serialProcess([1, 2, 3, 4, 5], (el, index, list, done) => {
  console.log(`${el} start`);
  setTimeout(() => {
    console.log(`${el} end`);
    done(el * el);
  }, el * 100);
}).then((list) => console.log(list)); // [1, 4, 9, 16, 25]

Требования:

  • Каждый элемент обрабатывается только после завершения предыдущего.
  • Обработчик может быть асинхронным (например, содержать setTimeout).
  • Результаты собираются в массив в том же порядке, что и исходные элементы.
  • После обработки всех элементов промис резолвится с массивом результатов.

Критерии

Домашнее задание ""Принято"" при наборе 3 и более баллов, иначе ""На доработку"".

  1. Создан и настроен новый репозиторий (пустой первый коммит, линтервы, тесты, пайплайны) , решены задачи, покрытие тестами от 50% - 3 балла
  2. Покрытие тестами от 70% - +1 балл
  3. Сделано ревью 1 PR другого студента с 5+ комментариями - +1 балл

Максимальный балл - 5.