Установка тайм‑аута для асинхронных функций

Обёртка запускает функцию и таймер на каждый вызов; кто завершится первым, определяет результат. Таймер нужно очищать после завершения операции.

Короткий ответ

Что ответить на собеседовании

Обёртка запускает функцию и таймер на каждый вызов; кто завершится первым, определяет результат. Таймер нужно очищать после завершения операции.

Подробный разбор

Ответ с пояснениями

Условие

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

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

Примеры использования:

const fn = async (n) => {
    await new Promise(res => setTimeout(res, 100));
    return n + n;
}

asyncLimit(fn, 50); // rejected; "Превышен лимит времени исполнения"
asyncLimit(fn, 150); // resolved; 25

const fn2 = async (a, b) => {
    await new Promise(res => setTimeout(res, 120));
    return a + b;
}

asyncLimit(fn2, 100)(1, 2); // rejected; "Превышен лимит времени исполнения"
asyncLimit(fn2, 150)(1, 2); // resolved; 3

Ответ

Обёртка запускает функцию и таймер на каждый вызов; кто завершится первым, определяет результат. Таймер нужно очищать после завершения операции.

function asyncLimit(fn, ms) {
  if (!Number.isFinite(ms) || ms < 0 || ms > 2147483647) throw new RangeError('Неверный таймаут');
  return function (...args) {
    return new Promise((resolve, reject) => {
      const timer = setTimeout(() => reject(new Error('Превышен лимит времени исполнения')), ms);
      Promise.resolve().then(() => fn.apply(this, args)).then(
        value => { clearTimeout(timer); resolve(value); },
        error => { clearTimeout(timer); reject(error); }
      );
    });
  };
}

В первых примерах условия отсутствует вызов возвращённой функции: нужен, например, asyncLimit(fn, 150)(12.5) для результата 25. Таймаут не отменяет исходную операцию и не может прервать блокирующий синхронный код.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее